1*33318Sdonn /* 2*33318Sdonn * Copyright (c) 1983 Regents of the University of California. 3*33318Sdonn * All rights reserved. The Berkeley software License Agreement 4*33318Sdonn * specifies the terms and conditions for redistribution. 5*33318Sdonn */ 6*33318Sdonn 7*33318Sdonn #ifndef lint 8*33318Sdonn static char sccsid[] = "@(#)iris.c 5.1 (Berkeley) 01/12/88"; 9*33318Sdonn #endif not lint 10*33318Sdonn 11*33318Sdonn static char rcsid[] = "$Header: machine.c,v 1.2 87/03/26 14:54:55 donn Exp $"; 12*33318Sdonn 13*33318Sdonn /* 14*33318Sdonn * Target machine dependent stuff. 15*33318Sdonn */ 16*33318Sdonn 17*33318Sdonn #include "defs.h" 18*33318Sdonn #include "machine.h" 19*33318Sdonn #include "process.h" 20*33318Sdonn #include "runtime.h" 21*33318Sdonn #include "events.h" 22*33318Sdonn #include "main.h" 23*33318Sdonn #include "symbols.h" 24*33318Sdonn #include "source.h" 25*33318Sdonn #include "mappings.h" 26*33318Sdonn #include "object.h" 27*33318Sdonn #include "tree.h" 28*33318Sdonn #include "eval.h" 29*33318Sdonn #include "keywords.h" 30*33318Sdonn #include "ops.h" 31*33318Sdonn 32*33318Sdonn #ifndef public 33*33318Sdonn typedef unsigned int Address; 34*33318Sdonn typedef unsigned char Byte; 35*33318Sdonn typedef unsigned int Word; 36*33318Sdonn 37*33318Sdonn /* 38*33318Sdonn * On the 68000, the pc isn't in a register, but we make believe 39*33318Sdonn * so there's one more register. 40*33318Sdonn * 41*33318Sdonn * Note that there's also no argument pointer, this means code 42*33318Sdonn * involving "ARGP" should always be #ifdef'd. 43*33318Sdonn * 44*33318Sdonn * The address corresponding to the beginning of a function is recorded 45*33318Sdonn * as the address + FUNCOFFSET (skip the link instruction so that 46*33318Sdonn * local information is available). 47*33318Sdonn */ 48*33318Sdonn 49*33318Sdonn #define NREG 17 50*33318Sdonn 51*33318Sdonn #define FRP 14 52*33318Sdonn #define STKP 15 53*33318Sdonn #define PROGCTR 16 54*33318Sdonn 55*33318Sdonn #define CALL_RETADDR 0x800c /* Return address for 'call' command */ 56*33318Sdonn #define FUNCOFFSET 4 57*33318Sdonn 58*33318Sdonn #ifdef sun 59*33318Sdonn # define CODESTART 0x8000 60*33318Sdonn #else /* IRIS */ 61*33318Sdonn # define CODESTART 0x1000 62*33318Sdonn #endif 63*33318Sdonn 64*33318Sdonn #define optab_init() 65*33318Sdonn 66*33318Sdonn #define BITSPERBYTE 8 67*33318Sdonn #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 68*33318Sdonn 69*33318Sdonn /* 70*33318Sdonn * This magic macro enables us to look at the process' registers 71*33318Sdonn * in its user structure. 72*33318Sdonn */ 73*33318Sdonn 74*33318Sdonn #define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * ((reg) - PC)) - 10) 75*33318Sdonn 76*33318Sdonn #include "source.h" 77*33318Sdonn #include "symbols.h" 78*33318Sdonn #include <signal.h> 79*33318Sdonn #include <sys/param.h> 80*33318Sdonn #include <sys/dir.h> 81*33318Sdonn #include <machine/psl.h> 82*33318Sdonn #include <machine/pte.h> 83*33318Sdonn #include <sys/user.h> 84*33318Sdonn #undef DELETE /* XXX */ 85*33318Sdonn #include <sys/vm.h> 86*33318Sdonn #include <machine/reg.h> 87*33318Sdonn 88*33318Sdonn Address pc; 89*33318Sdonn Address prtaddr; 90*33318Sdonn 91*33318Sdonn #endif 92*33318Sdonn 93*33318Sdonn /* 94*33318Sdonn * Indices into u. for use in collecting registers values. 95*33318Sdonn */ 96*33318Sdonn public int rloc[] ={ 97*33318Sdonn #ifdef sun 98*33318Sdonn R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, PC 99*33318Sdonn #else /* IRIS */ 100*33318Sdonn R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, 16 101*33318Sdonn #endif 102*33318Sdonn }; 103*33318Sdonn 104*33318Sdonn private Address printop(); 105*33318Sdonn 106*33318Sdonn /* 107*33318Sdonn * Decode and print the instructions within the given address range. 108*33318Sdonn */ 109*33318Sdonn 110*33318Sdonn public printinst(lowaddr, highaddr) 111*33318Sdonn Address lowaddr; 112*33318Sdonn Address highaddr; 113*33318Sdonn { 114*33318Sdonn register Address addr; 115*33318Sdonn 116*33318Sdonn for (addr = lowaddr; addr <= highaddr; ) { 117*33318Sdonn addr = printop(addr); 118*33318Sdonn } 119*33318Sdonn prtaddr = addr; 120*33318Sdonn } 121*33318Sdonn 122*33318Sdonn /* 123*33318Sdonn * Another approach: print n instructions starting at the given address. 124*33318Sdonn */ 125*33318Sdonn 126*33318Sdonn public printninst(count, addr) 127*33318Sdonn int count; 128*33318Sdonn Address addr; 129*33318Sdonn { 130*33318Sdonn register Integer i; 131*33318Sdonn register Address newaddr; 132*33318Sdonn 133*33318Sdonn if (count <= 0) { 134*33318Sdonn error("non-positive repetition count"); 135*33318Sdonn } else { 136*33318Sdonn newaddr = addr; 137*33318Sdonn for (i = 0; i < count; i++) { 138*33318Sdonn newaddr = printop(newaddr); 139*33318Sdonn } 140*33318Sdonn prtaddr = newaddr; 141*33318Sdonn } 142*33318Sdonn } 143*33318Sdonn 144*33318Sdonn /* 145*33318Sdonn * Print the contents of the addresses within the given range 146*33318Sdonn * according to the given format. 147*33318Sdonn */ 148*33318Sdonn 149*33318Sdonn typedef struct { 150*33318Sdonn String name; 151*33318Sdonn String printfstring; 152*33318Sdonn int length; 153*33318Sdonn } Format; 154*33318Sdonn 155*33318Sdonn private Format fmt[] = { 156*33318Sdonn { "d", " %d", sizeof(short) }, 157*33318Sdonn { "D", " %ld", sizeof(long) }, 158*33318Sdonn { "o", " %o", sizeof(short) }, 159*33318Sdonn { "O", " %lo", sizeof(long) }, 160*33318Sdonn { "x", " %04x", sizeof(short) }, 161*33318Sdonn { "X", " %08x", sizeof(long) }, 162*33318Sdonn { "b", " \\%o", sizeof(char) }, 163*33318Sdonn { "c", " '%c'", sizeof(char) }, 164*33318Sdonn { "s", "%c", sizeof(char) }, 165*33318Sdonn { "f", " %f", sizeof(float) }, 166*33318Sdonn { "g", " %g", sizeof(double) }, 167*33318Sdonn { nil, nil, 0 } 168*33318Sdonn }; 169*33318Sdonn 170*33318Sdonn private Format *findformat(s) 171*33318Sdonn String s; 172*33318Sdonn { 173*33318Sdonn register Format *f; 174*33318Sdonn 175*33318Sdonn f = &fmt[0]; 176*33318Sdonn while (f->name != nil and not streq(f->name, s)) { 177*33318Sdonn ++f; 178*33318Sdonn } 179*33318Sdonn if (f->name == nil) { 180*33318Sdonn error("bad print format \"%s\"", s); 181*33318Sdonn } 182*33318Sdonn return f; 183*33318Sdonn } 184*33318Sdonn 185*33318Sdonn /* 186*33318Sdonn * Retrieve and print out the appropriate data in the given format. 187*33318Sdonn * Floats have to be handled specially to allow the compiler to 188*33318Sdonn * convert them to doubles when passing to printf. 189*33318Sdonn */ 190*33318Sdonn 191*33318Sdonn private printformat (f, addr) 192*33318Sdonn Format *f; 193*33318Sdonn Address addr; 194*33318Sdonn { 195*33318Sdonn union { 196*33318Sdonn char charv; 197*33318Sdonn short shortv; 198*33318Sdonn int intv; 199*33318Sdonn float floatv; 200*33318Sdonn double doublev; 201*33318Sdonn } value; 202*33318Sdonn 203*33318Sdonn value.intv = 0; 204*33318Sdonn dread(&value, addr, f->length); 205*33318Sdonn if (streq(f->name, "f")) { 206*33318Sdonn printf(f->printfstring, value.floatv); 207*33318Sdonn } else { 208*33318Sdonn printf(f->printfstring, value); 209*33318Sdonn } 210*33318Sdonn } 211*33318Sdonn 212*33318Sdonn public Address printdata(lowaddr, highaddr, format) 213*33318Sdonn Address lowaddr; 214*33318Sdonn Address highaddr; 215*33318Sdonn String format; 216*33318Sdonn { 217*33318Sdonn int n; 218*33318Sdonn register Address addr; 219*33318Sdonn Format *f; 220*33318Sdonn 221*33318Sdonn if (lowaddr > highaddr) { 222*33318Sdonn error("first address larger than second"); 223*33318Sdonn } 224*33318Sdonn f = findformat(format); 225*33318Sdonn n = 0; 226*33318Sdonn for (addr = lowaddr; addr <= highaddr; addr += f->length) { 227*33318Sdonn if (n == 0) { 228*33318Sdonn printf("%08x: ", addr); 229*33318Sdonn } 230*33318Sdonn printformat(f, addr); 231*33318Sdonn ++n; 232*33318Sdonn if (n >= (16 div f->length)) { 233*33318Sdonn printf("\n"); 234*33318Sdonn n = 0; 235*33318Sdonn } 236*33318Sdonn } 237*33318Sdonn if (n != 0) { 238*33318Sdonn printf("\n"); 239*33318Sdonn } 240*33318Sdonn prtaddr = addr; 241*33318Sdonn return addr; 242*33318Sdonn } 243*33318Sdonn 244*33318Sdonn /* 245*33318Sdonn * The other approach is to print n items starting with a given address. 246*33318Sdonn */ 247*33318Sdonn 248*33318Sdonn public printndata(count, startaddr, format) 249*33318Sdonn int count; 250*33318Sdonn Address startaddr; 251*33318Sdonn String format; 252*33318Sdonn { 253*33318Sdonn int i, n; 254*33318Sdonn Address addr; 255*33318Sdonn Format *f; 256*33318Sdonn Boolean isstring; 257*33318Sdonn char c; 258*33318Sdonn 259*33318Sdonn if (count <= 0) { 260*33318Sdonn error("non-positive repetition count"); 261*33318Sdonn } 262*33318Sdonn f = findformat(format); 263*33318Sdonn isstring = (Boolean) streq(f->name, "s"); 264*33318Sdonn n = 0; 265*33318Sdonn addr = startaddr; 266*33318Sdonn for (i = 0; i < count; i++) { 267*33318Sdonn if (n == 0) { 268*33318Sdonn printf("%08x: ", addr); 269*33318Sdonn } 270*33318Sdonn if (isstring) { 271*33318Sdonn printf("\""); 272*33318Sdonn dread(&c, addr, sizeof(char)); 273*33318Sdonn while (c != '\0') { 274*33318Sdonn printchar(c); 275*33318Sdonn ++addr; 276*33318Sdonn dread(&c, addr, sizeof(char)); 277*33318Sdonn } 278*33318Sdonn printf("\"\n"); 279*33318Sdonn n = 0; 280*33318Sdonn addr += sizeof(String); 281*33318Sdonn } else { 282*33318Sdonn printformat(f, addr); 283*33318Sdonn ++n; 284*33318Sdonn if (n >= (16 div f->length)) { 285*33318Sdonn printf("\n"); 286*33318Sdonn n = 0; 287*33318Sdonn } 288*33318Sdonn addr += f->length; 289*33318Sdonn } 290*33318Sdonn } 291*33318Sdonn if (n != 0) { 292*33318Sdonn printf("\n"); 293*33318Sdonn } 294*33318Sdonn prtaddr = addr; 295*33318Sdonn } 296*33318Sdonn 297*33318Sdonn /* 298*33318Sdonn * Print out a value according to the given format. 299*33318Sdonn */ 300*33318Sdonn 301*33318Sdonn public printvalue(v, format) 302*33318Sdonn long v; 303*33318Sdonn String format; 304*33318Sdonn { 305*33318Sdonn Format *f; 306*33318Sdonn char *p, *q; 307*33318Sdonn 308*33318Sdonn f = findformat(format); 309*33318Sdonn if (streq(f->name, "s")) { 310*33318Sdonn putchar('"'); 311*33318Sdonn p = (char *) &v; 312*33318Sdonn q = p + sizeof(v); 313*33318Sdonn while (p < q) { 314*33318Sdonn printchar(*p); 315*33318Sdonn ++p; 316*33318Sdonn } 317*33318Sdonn putchar('"'); 318*33318Sdonn } else { 319*33318Sdonn printf(f->printfstring, v); 320*33318Sdonn } 321*33318Sdonn putchar('\n'); 322*33318Sdonn } 323*33318Sdonn 324*33318Sdonn /* 325*33318Sdonn * Print out an execution time error. 326*33318Sdonn * Assumes the source position of the error has been calculated. 327*33318Sdonn * 328*33318Sdonn * Have to check if the -r option was specified; if so then 329*33318Sdonn * the object file information hasn't been read in yet. 330*33318Sdonn */ 331*33318Sdonn 332*33318Sdonn public printerror() 333*33318Sdonn { 334*33318Sdonn extern Integer sys_nsig; 335*33318Sdonn extern String sys_siglist[]; 336*33318Sdonn integer err; 337*33318Sdonn 338*33318Sdonn if (isfinished(process)) { 339*33318Sdonn err = exitcode(process); 340*33318Sdonn if (err == 0) { 341*33318Sdonn printf("\"%s\" terminated normally\n", objname); 342*33318Sdonn } else { 343*33318Sdonn printf("\"%s\" terminated abnormally (exit code %d)\n", 344*33318Sdonn objname, err 345*33318Sdonn ); 346*33318Sdonn } 347*33318Sdonn erecover(); 348*33318Sdonn } 349*33318Sdonn err = errnum(process); 350*33318Sdonn putchar('\n'); 351*33318Sdonn printsig(err); 352*33318Sdonn putchar(' '); 353*33318Sdonn printloc(); 354*33318Sdonn putchar('\n'); 355*33318Sdonn if (curline > 0) { 356*33318Sdonn printlines(curline, curline); 357*33318Sdonn } else { 358*33318Sdonn printinst(pc, pc); 359*33318Sdonn } 360*33318Sdonn erecover(); 361*33318Sdonn } 362*33318Sdonn 363*33318Sdonn /* 364*33318Sdonn * Print out a signal. 365*33318Sdonn */ 366*33318Sdonn 367*33318Sdonn private String illinames[] = { 368*33318Sdonn "reserved addressing fault", 369*33318Sdonn "privileged instruction fault", 370*33318Sdonn "reserved operand fault" 371*33318Sdonn }; 372*33318Sdonn 373*33318Sdonn private String fpenames[] = { 374*33318Sdonn nil, 375*33318Sdonn "integer overflow trap", 376*33318Sdonn "integer divide by zero trap", 377*33318Sdonn "floating overflow trap", 378*33318Sdonn "floating/decimal divide by zero trap", 379*33318Sdonn "floating underflow trap", 380*33318Sdonn "decimal overflow trap", 381*33318Sdonn "subscript out of range trap", 382*33318Sdonn "floating overflow fault", 383*33318Sdonn "floating divide by zero fault", 384*33318Sdonn "floating underflow fault" 385*33318Sdonn }; 386*33318Sdonn 387*33318Sdonn public printsig (signo) 388*33318Sdonn integer signo; 389*33318Sdonn { 390*33318Sdonn integer code; 391*33318Sdonn 392*33318Sdonn if (signo < 0 or signo > sys_nsig) { 393*33318Sdonn printf("[signal %d]", signo); 394*33318Sdonn } else { 395*33318Sdonn printf("%s", sys_siglist[signo]); 396*33318Sdonn } 397*33318Sdonn code = errcode(process); 398*33318Sdonn if (signo == SIGILL) { 399*33318Sdonn if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { 400*33318Sdonn printf(" (%s)", illinames[code]); 401*33318Sdonn } 402*33318Sdonn } else if (signo == SIGFPE) { 403*33318Sdonn if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { 404*33318Sdonn printf(" (%s)", fpenames[code]); 405*33318Sdonn } 406*33318Sdonn } 407*33318Sdonn } 408*33318Sdonn 409*33318Sdonn /* 410*33318Sdonn * Note the termination of the program. We do this so as to avoid 411*33318Sdonn * having the process exit, which would make the values of variables 412*33318Sdonn * inaccessible. We do want to flush all output buffers here, 413*33318Sdonn * otherwise it'll never get done. 414*33318Sdonn */ 415*33318Sdonn 416*33318Sdonn public endprogram() 417*33318Sdonn { 418*33318Sdonn Integer exitcode; 419*33318Sdonn 420*33318Sdonn stepto(nextaddr(pc, true)); 421*33318Sdonn printnews(); 422*33318Sdonn exitcode = argn(1, nil); 423*33318Sdonn if (exitcode != 0) { 424*33318Sdonn printf("\nexecution completed (exit code %d)\n", exitcode); 425*33318Sdonn } else { 426*33318Sdonn printf("\nexecution completed\n"); 427*33318Sdonn } 428*33318Sdonn getsrcpos(); 429*33318Sdonn erecover(); 430*33318Sdonn } 431*33318Sdonn 432*33318Sdonn /* 433*33318Sdonn * Single step the machine a source line (or instruction if "inst_tracing" 434*33318Sdonn * is true). If "isnext" is true, skip over procedure calls. 435*33318Sdonn */ 436*33318Sdonn 437*33318Sdonn private Address getcall(); 438*33318Sdonn 439*33318Sdonn public dostep(isnext) 440*33318Sdonn Boolean isnext; 441*33318Sdonn { 442*33318Sdonn register Address addr; 443*33318Sdonn register Lineno line; 444*33318Sdonn String filename; 445*33318Sdonn Address startaddr; 446*33318Sdonn 447*33318Sdonn startaddr = pc; 448*33318Sdonn addr = nextaddr(pc, isnext); 449*33318Sdonn if (not inst_tracing and nlhdr.nlines != 0) { 450*33318Sdonn line = linelookup(addr); 451*33318Sdonn while (line == 0) { 452*33318Sdonn addr = nextaddr(addr, isnext); 453*33318Sdonn line = linelookup(addr); 454*33318Sdonn } 455*33318Sdonn curline = line; 456*33318Sdonn } else { 457*33318Sdonn curline = 0; 458*33318Sdonn } 459*33318Sdonn stepto(addr); 460*33318Sdonn filename = srcfilename(addr); 461*33318Sdonn setsource(filename); 462*33318Sdonn } 463*33318Sdonn 464*33318Sdonn typedef short Bpinst; 465*33318Sdonn 466*33318Sdonn extern Bpinst BP_OP; 467*33318Sdonn #ifdef sun 468*33318Sdonn asm("_BP_OP: trap #15"); 469*33318Sdonn #else /* IRIS */ 470*33318Sdonn asm("_BP_OP: trap #1"); 471*33318Sdonn #endif 472*33318Sdonn 473*33318Sdonn #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 474*33318Sdonn 475*33318Sdonn /* 476*33318Sdonn * Setting a breakpoint at a location consists of saving 477*33318Sdonn * the word at the location and poking a BP_OP there. 478*33318Sdonn * 479*33318Sdonn * We save the locations and words on a list for use in unsetting. 480*33318Sdonn */ 481*33318Sdonn 482*33318Sdonn typedef struct Savelist *Savelist; 483*33318Sdonn 484*33318Sdonn struct Savelist { 485*33318Sdonn Address location; 486*33318Sdonn Bpinst save; 487*33318Sdonn short refcount; 488*33318Sdonn Savelist link; 489*33318Sdonn }; 490*33318Sdonn 491*33318Sdonn private Savelist savelist; 492*33318Sdonn 493*33318Sdonn /* 494*33318Sdonn * Set a breakpoint at the given address. Only save the word there 495*33318Sdonn * if it's not already a breakpoint. 496*33318Sdonn */ 497*33318Sdonn 498*33318Sdonn public setbp(addr) 499*33318Sdonn Address addr; 500*33318Sdonn { 501*33318Sdonn Bpinst w, save; 502*33318Sdonn register Savelist newsave, s; 503*33318Sdonn 504*33318Sdonn for (s = savelist; s != nil; s = s->link) { 505*33318Sdonn if (s->location == addr) { 506*33318Sdonn s->refcount++; 507*33318Sdonn return; 508*33318Sdonn } 509*33318Sdonn } 510*33318Sdonn iread(&save, addr, sizeof(save)); 511*33318Sdonn newsave = new(Savelist); 512*33318Sdonn newsave->location = addr; 513*33318Sdonn newsave->save = save; 514*33318Sdonn newsave->refcount = 1; 515*33318Sdonn newsave->link = savelist; 516*33318Sdonn savelist = newsave; 517*33318Sdonn w = BP_OP; 518*33318Sdonn iwrite(&w, addr, sizeof(w)); 519*33318Sdonn } 520*33318Sdonn 521*33318Sdonn /* 522*33318Sdonn * Unset a breakpoint; unfortunately we have to search the SAVELIST 523*33318Sdonn * to find the saved value. The assumption is that the SAVELIST will 524*33318Sdonn * usually be quite small. 525*33318Sdonn */ 526*33318Sdonn 527*33318Sdonn public unsetbp(addr) 528*33318Sdonn Address addr; 529*33318Sdonn { 530*33318Sdonn register Savelist s, prev; 531*33318Sdonn 532*33318Sdonn prev = nil; 533*33318Sdonn for (s = savelist; s != nil; s = s->link) { 534*33318Sdonn if (s->location == addr) { 535*33318Sdonn iwrite(&s->save, addr, sizeof(s->save)); 536*33318Sdonn s->refcount--; 537*33318Sdonn if (s->refcount == 0) { 538*33318Sdonn if (prev == nil) { 539*33318Sdonn savelist = s->link; 540*33318Sdonn } else { 541*33318Sdonn prev->link = s->link; 542*33318Sdonn } 543*33318Sdonn dispose(s); 544*33318Sdonn } 545*33318Sdonn return; 546*33318Sdonn } 547*33318Sdonn prev = s; 548*33318Sdonn } 549*33318Sdonn panic("unsetbp: couldn't find address %d", addr); 550*33318Sdonn } 551*33318Sdonn 552*33318Sdonn /* 553*33318Sdonn * Instruction decoding routines for 68000, derived from adb. 554*33318Sdonn * 555*33318Sdonn * The shared boolean variable "printing" is true if the decoded 556*33318Sdonn * instruction is to be printed, false if not. In either case, 557*33318Sdonn * the address of the next instruction after the given one is returned. 558*33318Sdonn */ 559*33318Sdonn 560*33318Sdonn private Boolean printing; 561*33318Sdonn private Boolean following; 562*33318Sdonn private Boolean followcalls; 563*33318Sdonn private Address instaddr; 564*33318Sdonn 565*33318Sdonn #define instread(var) \ 566*33318Sdonn { \ 567*33318Sdonn iread(&var, instaddr, sizeof(var)); \ 568*33318Sdonn instaddr += sizeof(var); \ 569*33318Sdonn } 570*33318Sdonn 571*33318Sdonn private Optab *decode(inst, addr) 572*33318Sdonn Word inst; 573*33318Sdonn Address addr; 574*33318Sdonn { 575*33318Sdonn register Optab *o; 576*33318Sdonn 577*33318Sdonn o = &optab[0]; 578*33318Sdonn while (o->mask != 0 and (inst&o->mask) != o->match) { 579*33318Sdonn ++o; 580*33318Sdonn } 581*33318Sdonn return o; 582*33318Sdonn } 583*33318Sdonn 584*33318Sdonn private Address printop(addr) 585*33318Sdonn Address addr; 586*33318Sdonn { 587*33318Sdonn Optab *o; 588*33318Sdonn short inst; 589*33318Sdonn 590*33318Sdonn printf("%08x ", addr); 591*33318Sdonn iread(&inst, addr, sizeof(inst)); 592*33318Sdonn o = decode(inst, addr); 593*33318Sdonn if (o->mask == 0) { 594*33318Sdonn printf("\tbadop"); 595*33318Sdonn instaddr = addr + sizeof(inst); 596*33318Sdonn } else { 597*33318Sdonn printing = true; 598*33318Sdonn following = false; 599*33318Sdonn instaddr = addr + sizeof(inst); 600*33318Sdonn (*o->opfun)(inst, o->farg); 601*33318Sdonn printing = false; 602*33318Sdonn } 603*33318Sdonn printf("\n"); 604*33318Sdonn return instaddr; 605*33318Sdonn } 606*33318Sdonn 607*33318Sdonn /* 608*33318Sdonn * Quickly find the return address of the current procedure or function 609*33318Sdonn * while single stepping. Just get the word pointed at by sp. 610*33318Sdonn */ 611*33318Sdonn 612*33318Sdonn private Address currtnaddr () 613*33318Sdonn { 614*33318Sdonn Address retaddr; 615*33318Sdonn 616*33318Sdonn dread(&retaddr, reg(STKP), sizeof(retaddr)); 617*33318Sdonn return retaddr; 618*33318Sdonn } 619*33318Sdonn 620*33318Sdonn /* 621*33318Sdonn * Print out the effective address for the given parameters. 622*33318Sdonn */ 623*33318Sdonn 624*33318Sdonn private printea(mode, reg, size) 625*33318Sdonn long mode, reg; 626*33318Sdonn int size; 627*33318Sdonn { 628*33318Sdonn long index, disp; 629*33318Sdonn static char *aregs[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp" }; 630*33318Sdonn Byte b; 631*33318Sdonn short w; 632*33318Sdonn long l; 633*33318Sdonn 634*33318Sdonn switch ((int)(mode)) { 635*33318Sdonn case 0: 636*33318Sdonn if (printing) { 637*33318Sdonn printf("d%D", reg); 638*33318Sdonn } 639*33318Sdonn break; 640*33318Sdonn 641*33318Sdonn case 1: 642*33318Sdonn if (printing) { 643*33318Sdonn printf("%s", aregs[reg]); 644*33318Sdonn } 645*33318Sdonn break; 646*33318Sdonn 647*33318Sdonn case 2: 648*33318Sdonn if (printing) { 649*33318Sdonn printf("%s@", aregs[reg]); 650*33318Sdonn } 651*33318Sdonn break; 652*33318Sdonn 653*33318Sdonn case 3: 654*33318Sdonn if (printing) { 655*33318Sdonn printf("%s@+", aregs[reg]); 656*33318Sdonn } 657*33318Sdonn break; 658*33318Sdonn 659*33318Sdonn case 4: 660*33318Sdonn if (printing) { 661*33318Sdonn printf("%s@-", aregs[reg]); 662*33318Sdonn } 663*33318Sdonn break; 664*33318Sdonn 665*33318Sdonn case 5: 666*33318Sdonn instread(w); 667*33318Sdonn if (printing) { 668*33318Sdonn printf("%s@(%D)", aregs[reg], w); 669*33318Sdonn } 670*33318Sdonn break; 671*33318Sdonn 672*33318Sdonn case 6: 673*33318Sdonn instread(w); 674*33318Sdonn if (printing) { 675*33318Sdonn index = w; 676*33318Sdonn disp = (char)(index&0377); 677*33318Sdonn printf("%s@(%d,%c%D:%c)", aregs[reg], disp, 678*33318Sdonn (index&0100000)?'a':'d',(index>>12)&07, 679*33318Sdonn (index&04000)?'l':'w'); 680*33318Sdonn } 681*33318Sdonn break; 682*33318Sdonn 683*33318Sdonn case 7: 684*33318Sdonn switch ((int)(reg)) { 685*33318Sdonn case 0: 686*33318Sdonn instread(w); 687*33318Sdonn if (printing) { 688*33318Sdonn index = w; 689*33318Sdonn psymoff(index); 690*33318Sdonn } 691*33318Sdonn break; 692*33318Sdonn 693*33318Sdonn case 1: 694*33318Sdonn instread(l); 695*33318Sdonn if (printing) { 696*33318Sdonn index = l; 697*33318Sdonn psymoff(index); 698*33318Sdonn } 699*33318Sdonn break; 700*33318Sdonn 701*33318Sdonn case 2: 702*33318Sdonn instread(w); 703*33318Sdonn if (printing) { 704*33318Sdonn disp = w; 705*33318Sdonn psymoff(disp + instaddr); 706*33318Sdonn } 707*33318Sdonn break; 708*33318Sdonn 709*33318Sdonn case 3: 710*33318Sdonn instread(w); 711*33318Sdonn if (printing) { 712*33318Sdonn index = w; 713*33318Sdonn disp = (char)(index&0377); 714*33318Sdonn printf("pc@(%D,%c%D:%c)", disp, 715*33318Sdonn (index&0100000)?'a':'d',(index>>12)&07, 716*33318Sdonn (index&04000)?'l':'w'); 717*33318Sdonn } 718*33318Sdonn break; 719*33318Sdonn 720*33318Sdonn case 4: 721*33318Sdonn switch (size) { 722*33318Sdonn case sizeof(b): 723*33318Sdonn instread(w); 724*33318Sdonn index = (w&0xff); 725*33318Sdonn break; 726*33318Sdonn 727*33318Sdonn case sizeof(w): 728*33318Sdonn instread(w); 729*33318Sdonn index = w; 730*33318Sdonn break; 731*33318Sdonn 732*33318Sdonn case sizeof(l): 733*33318Sdonn instread(l); 734*33318Sdonn index = l; 735*33318Sdonn break; 736*33318Sdonn 737*33318Sdonn default: 738*33318Sdonn if (printing) { 739*33318Sdonn printf("unexpected size %d in printea\n", size); 740*33318Sdonn } 741*33318Sdonn instread(l); 742*33318Sdonn index = l; 743*33318Sdonn break; 744*33318Sdonn } 745*33318Sdonn if (printing) { 746*33318Sdonn printf(IMDF, index); 747*33318Sdonn } 748*33318Sdonn break; 749*33318Sdonn 750*33318Sdonn default: 751*33318Sdonn if (printing) { 752*33318Sdonn printf("???"); 753*33318Sdonn } 754*33318Sdonn break; 755*33318Sdonn } 756*33318Sdonn break; 757*33318Sdonn 758*33318Sdonn default: 759*33318Sdonn if (printing) { 760*33318Sdonn printf("???"); 761*33318Sdonn } 762*33318Sdonn break; 763*33318Sdonn } 764*33318Sdonn } 765*33318Sdonn 766*33318Sdonn private printEA(ea, size) 767*33318Sdonn long ea; 768*33318Sdonn int size; 769*33318Sdonn { 770*33318Sdonn printea((ea>>3)&07, ea&07, size); 771*33318Sdonn } 772*33318Sdonn 773*33318Sdonn private mapsize(inst) 774*33318Sdonn register long inst; 775*33318Sdonn { 776*33318Sdonn int m; 777*33318Sdonn 778*33318Sdonn inst >>= 6; 779*33318Sdonn inst &= 03; 780*33318Sdonn switch (inst) { 781*33318Sdonn case 0: 782*33318Sdonn m = 1; 783*33318Sdonn break; 784*33318Sdonn 785*33318Sdonn case 1: 786*33318Sdonn m = 2; 787*33318Sdonn break; 788*33318Sdonn 789*33318Sdonn case 2: 790*33318Sdonn m = 4; 791*33318Sdonn break; 792*33318Sdonn 793*33318Sdonn default: 794*33318Sdonn m = -1; 795*33318Sdonn break; 796*33318Sdonn } 797*33318Sdonn return m; 798*33318Sdonn } 799*33318Sdonn 800*33318Sdonn private char suffix(size) 801*33318Sdonn int size; 802*33318Sdonn { 803*33318Sdonn char c; 804*33318Sdonn 805*33318Sdonn switch (size) { 806*33318Sdonn case 1: 807*33318Sdonn c = 'b'; 808*33318Sdonn break; 809*33318Sdonn 810*33318Sdonn case 2: 811*33318Sdonn c = 'w'; 812*33318Sdonn break; 813*33318Sdonn 814*33318Sdonn case 4: 815*33318Sdonn c = 'l'; 816*33318Sdonn break; 817*33318Sdonn 818*33318Sdonn default: 819*33318Sdonn panic("bad size %d in suffix", size); 820*33318Sdonn } 821*33318Sdonn return c; 822*33318Sdonn } 823*33318Sdonn 824*33318Sdonn /* 825*33318Sdonn * Print an address offset. Eventually this should attempt to be symbolic, 826*33318Sdonn * but for now its just printed in hex. 827*33318Sdonn */ 828*33318Sdonn 829*33318Sdonn private psymoff (off) 830*33318Sdonn Word off; 831*33318Sdonn { 832*33318Sdonn Symbol f; 833*33318Sdonn 834*33318Sdonn f = whatblock((Address) (off + FUNCOFFSET)); 835*33318Sdonn if (codeloc(f) == off + FUNCOFFSET) { 836*33318Sdonn printf("%s", symname(f)); 837*33318Sdonn } else { 838*33318Sdonn printf("0x%x", off); 839*33318Sdonn } 840*33318Sdonn } 841*33318Sdonn 842*33318Sdonn /* 843*33318Sdonn * Instruction class specific routines. 844*33318Sdonn */ 845*33318Sdonn 846*33318Sdonn public omove(inst, s) 847*33318Sdonn long inst; 848*33318Sdonn String s; 849*33318Sdonn { 850*33318Sdonn register int c; 851*33318Sdonn int size; 852*33318Sdonn 853*33318Sdonn c = s[0]; 854*33318Sdonn if (printing) { 855*33318Sdonn printf("\tmov%c\t", c); 856*33318Sdonn } 857*33318Sdonn size = ((c == 'b') ? 1 : (c == 'w') ? 2 : 4); 858*33318Sdonn printea((inst>>3)&07, inst&07, size); 859*33318Sdonn if (printing) { 860*33318Sdonn printf(","); 861*33318Sdonn } 862*33318Sdonn printea((inst>>6)&07, (inst>>9)&07, size); 863*33318Sdonn } 864*33318Sdonn 865*33318Sdonn /* 866*33318Sdonn * Two types: bsr (4 bytes) and bsrs (2 bytes) 867*33318Sdonn */ 868*33318Sdonn 869*33318Sdonn public obranch(inst, dummy) 870*33318Sdonn long inst; 871*33318Sdonn { 872*33318Sdonn long disp; 873*33318Sdonn String s; 874*33318Sdonn short w; 875*33318Sdonn Address startingaddr; /* address of branch instruction */ 876*33318Sdonn int branchtype; /* type of branch (0 = unconditional) */ 877*33318Sdonn Address dest; 878*33318Sdonn Address retaddr; /* for bsr instruction */ 879*33318Sdonn 880*33318Sdonn startingaddr = instaddr - 2; 881*33318Sdonn disp = inst&0377; 882*33318Sdonn s = "s "; 883*33318Sdonn if (disp == 0) { 884*33318Sdonn retaddr = startingaddr + 4; 885*33318Sdonn } else { 886*33318Sdonn retaddr = startingaddr + 2; 887*33318Sdonn } 888*33318Sdonn if (disp > 127) { 889*33318Sdonn disp |= ~0377; 890*33318Sdonn } else if (disp == 0){ 891*33318Sdonn s = " "; 892*33318Sdonn instread(w); 893*33318Sdonn disp = w; 894*33318Sdonn } 895*33318Sdonn branchtype = (int)((inst>>8)&017); 896*33318Sdonn dest = startingaddr + 2 + disp; 897*33318Sdonn if (printing) { 898*33318Sdonn printf("\tb%s%s\t", bname[branchtype], s); 899*33318Sdonn psymoff(dest); 900*33318Sdonn } 901*33318Sdonn if (following) { 902*33318Sdonn /* 903*33318Sdonn * If we're to follow the dynamic flow of instructions, 904*33318Sdonn * we must see where the branch leads. A branchtype of 0 905*33318Sdonn * indicates an unconditional branch which we simply take 906*33318Sdonn * as the new instruction address. For a conditional branch, 907*33318Sdonn * we continue execution up to the current address, single step, 908*33318Sdonn * and keep going. 909*33318Sdonn */ 910*33318Sdonn if (branchtype == 0) { 911*33318Sdonn instaddr = dest; 912*33318Sdonn } else if (branchtype == 01) { /* bsr */ 913*33318Sdonn if (followcalls) { 914*33318Sdonn steppast(startingaddr); 915*33318Sdonn curfunc = whatblock(pc, true); 916*33318Sdonn if (not isbperr()) { 917*33318Sdonn printstatus(); 918*33318Sdonn /* NOTREACHED */ 919*33318Sdonn } 920*33318Sdonn bpact(); 921*33318Sdonn if (nosource(curfunc) and canskip(curfunc) and 922*33318Sdonn nlhdr.nlines != 0) { 923*33318Sdonn stepto(retaddr); 924*33318Sdonn instaddr = pc; 925*33318Sdonn bpact(); 926*33318Sdonn } else { 927*33318Sdonn callnews(/* iscall = */ true); 928*33318Sdonn } 929*33318Sdonn } 930*33318Sdonn } else { 931*33318Sdonn steppast(startingaddr); 932*33318Sdonn } 933*33318Sdonn } 934*33318Sdonn } 935*33318Sdonn 936*33318Sdonn public odbcc(inst, form) 937*33318Sdonn long inst; 938*33318Sdonn String form; 939*33318Sdonn { 940*33318Sdonn long disp; 941*33318Sdonn short w; 942*33318Sdonn 943*33318Sdonn instread(w); 944*33318Sdonn if (printing) { 945*33318Sdonn printf(form, dbname[(int)((inst>>8)&017)], inst&07); 946*33318Sdonn psymoff(w + sizeof(w)); 947*33318Sdonn } 948*33318Sdonn } 949*33318Sdonn 950*33318Sdonn public oscc(inst, dummy) 951*33318Sdonn long inst; 952*33318Sdonn long dummy; 953*33318Sdonn { 954*33318Sdonn if (printing) { 955*33318Sdonn printf("\ts%s\t", cname[(int)((inst>>8)&017)]); 956*33318Sdonn } 957*33318Sdonn printea((inst>>3)&07, inst&07, 1); 958*33318Sdonn } 959*33318Sdonn 960*33318Sdonn public biti(inst, dummy) 961*33318Sdonn long inst; 962*33318Sdonn long dummy; 963*33318Sdonn { 964*33318Sdonn short w; 965*33318Sdonn 966*33318Sdonn if (printing) { 967*33318Sdonn printf("\t%s\t", bit[(int)((inst>>6)&03)]); 968*33318Sdonn } 969*33318Sdonn if (inst&0x0100) { 970*33318Sdonn if (printing) { 971*33318Sdonn printf("d%D,", inst>>9); 972*33318Sdonn } 973*33318Sdonn } else { 974*33318Sdonn instread(w); 975*33318Sdonn if (printing) { 976*33318Sdonn printf(IMDF, w); 977*33318Sdonn printf(","); 978*33318Sdonn } 979*33318Sdonn } 980*33318Sdonn printEA(inst); 981*33318Sdonn } 982*33318Sdonn 983*33318Sdonn public opmode(inst, opcode) 984*33318Sdonn long inst; 985*33318Sdonn long opcode; 986*33318Sdonn { 987*33318Sdonn register int opmode; 988*33318Sdonn register int reg; 989*33318Sdonn int size; 990*33318Sdonn 991*33318Sdonn opmode = (int)((inst>>6) & 07); 992*33318Sdonn reg = (int)((inst>>9) & 07); 993*33318Sdonn if (opmode == 0 or opmode == 4) { 994*33318Sdonn size = 1; 995*33318Sdonn } else if (opmode == 1 or opmode == 3 or opmode == 5) { 996*33318Sdonn size = 2; 997*33318Sdonn } else { 998*33318Sdonn size = 4; 999*33318Sdonn } 1000*33318Sdonn if (printing) { 1001*33318Sdonn printf("\t%s%c\t", opcode, suffix(size)); 1002*33318Sdonn } 1003*33318Sdonn if (opmode >= 4 and opmode <= 6) { 1004*33318Sdonn if (printing) { 1005*33318Sdonn printf("d%d,", reg); 1006*33318Sdonn } 1007*33318Sdonn printea((inst>>3)&07, inst&07, size); 1008*33318Sdonn } else { 1009*33318Sdonn printea((inst>>3)&07, inst&07, size); 1010*33318Sdonn if (printing) { 1011*33318Sdonn printf(",%c%d",(opmode<=2) ? 'd' : 'a', reg); 1012*33318Sdonn } 1013*33318Sdonn } 1014*33318Sdonn } 1015*33318Sdonn 1016*33318Sdonn public shroi(inst, ds) 1017*33318Sdonn long inst; 1018*33318Sdonn String ds; 1019*33318Sdonn { 1020*33318Sdonn int rx, ry; 1021*33318Sdonn String opcode; 1022*33318Sdonn 1023*33318Sdonn if ((inst & 0xC0) == 0xC0) { 1024*33318Sdonn opcode = shro[(int)((inst>>9)&03)]; 1025*33318Sdonn if (printing) { 1026*33318Sdonn printf("\t%s%s\t", opcode, ds); 1027*33318Sdonn } 1028*33318Sdonn printEA(inst); 1029*33318Sdonn } else { 1030*33318Sdonn if (printing) { 1031*33318Sdonn opcode = shro[(int)((inst>>3)&03)]; 1032*33318Sdonn printf("\t%s%s%c\t", opcode, ds, suffix(mapsize(inst))); 1033*33318Sdonn rx = (int)((inst>>9)&07); ry = (int)(inst&07); 1034*33318Sdonn if ((inst>>5)&01) { 1035*33318Sdonn printf("d%d,d%d", rx, ry); 1036*33318Sdonn } else { 1037*33318Sdonn printf(IMDF, (rx ? rx : 8)); 1038*33318Sdonn printf(",d%d", ry); 1039*33318Sdonn } 1040*33318Sdonn } 1041*33318Sdonn } 1042*33318Sdonn } 1043*33318Sdonn 1044*33318Sdonn public oimmed(inst, opcode) 1045*33318Sdonn long inst; 1046*33318Sdonn register String opcode; 1047*33318Sdonn { 1048*33318Sdonn register int size; 1049*33318Sdonn long const; 1050*33318Sdonn short w; 1051*33318Sdonn 1052*33318Sdonn size = mapsize(inst); 1053*33318Sdonn if (size > 0) { 1054*33318Sdonn if (size == 4) { 1055*33318Sdonn instread(const); 1056*33318Sdonn } else { 1057*33318Sdonn instread(w); 1058*33318Sdonn const = w; 1059*33318Sdonn } 1060*33318Sdonn if (printing) { 1061*33318Sdonn printf("\t%s%c\t", opcode, suffix(size)); 1062*33318Sdonn printf(IMDF, const); 1063*33318Sdonn printf(","); 1064*33318Sdonn } 1065*33318Sdonn printEA(inst, size); 1066*33318Sdonn } else { 1067*33318Sdonn if (printing) { 1068*33318Sdonn printf("\tbadop"); 1069*33318Sdonn } 1070*33318Sdonn } 1071*33318Sdonn } 1072*33318Sdonn 1073*33318Sdonn public oreg(inst, opcode) 1074*33318Sdonn long inst; 1075*33318Sdonn register String opcode; 1076*33318Sdonn { 1077*33318Sdonn if (printing) { 1078*33318Sdonn printf(opcode, (inst & 07)); 1079*33318Sdonn } 1080*33318Sdonn } 1081*33318Sdonn 1082*33318Sdonn public extend(inst, opcode) 1083*33318Sdonn long inst; 1084*33318Sdonn String opcode; 1085*33318Sdonn { 1086*33318Sdonn register int size; 1087*33318Sdonn int ry, rx; 1088*33318Sdonn char c; 1089*33318Sdonn 1090*33318Sdonn if (printing) { 1091*33318Sdonn size = mapsize(inst); 1092*33318Sdonn ry = (inst&07); 1093*33318Sdonn rx = ((inst>>9)&07); 1094*33318Sdonn c = ((inst & 0x1000) ? suffix(size) : ' '); 1095*33318Sdonn printf("\t%s%c\t", opcode, c); 1096*33318Sdonn if (opcode[0] == 'e') { 1097*33318Sdonn if (inst & 0x0080) { 1098*33318Sdonn printf("d%D,a%D", rx, ry); 1099*33318Sdonn } else if (inst & 0x0008) { 1100*33318Sdonn printf("a%D,a%D", rx, ry); 1101*33318Sdonn } else { 1102*33318Sdonn printf("d%D,d%D", rx, ry); 1103*33318Sdonn } 1104*33318Sdonn } else if ((inst & 0xF000) == 0xB000) { 1105*33318Sdonn printf("a%D@+,a%D@+", ry, rx); 1106*33318Sdonn } else if (inst & 0x8) { 1107*33318Sdonn printf("a%D@-,a%D@-", ry, rx); 1108*33318Sdonn } else { 1109*33318Sdonn printf("d%D,d%D", ry, rx); 1110*33318Sdonn } 1111*33318Sdonn } 1112*33318Sdonn } 1113*33318Sdonn 1114*33318Sdonn public olink(inst, dummy) 1115*33318Sdonn long inst; 1116*33318Sdonn long dummy; 1117*33318Sdonn { 1118*33318Sdonn short w; 1119*33318Sdonn 1120*33318Sdonn instread(w); 1121*33318Sdonn if (printing) { 1122*33318Sdonn printf("\tlink\ta%D,", inst&07); 1123*33318Sdonn printf(IMDF, w); 1124*33318Sdonn } 1125*33318Sdonn } 1126*33318Sdonn 1127*33318Sdonn public otrap(inst, dummy) 1128*33318Sdonn long inst; 1129*33318Sdonn { 1130*33318Sdonn if (printing) { 1131*33318Sdonn printf("\ttrap\t"); 1132*33318Sdonn printf(IMDF, inst&017); 1133*33318Sdonn } 1134*33318Sdonn } 1135*33318Sdonn 1136*33318Sdonn public oneop(inst, opcode) 1137*33318Sdonn long inst; 1138*33318Sdonn register String opcode; 1139*33318Sdonn { 1140*33318Sdonn if (printing) { 1141*33318Sdonn printf("\t%s",opcode); 1142*33318Sdonn } 1143*33318Sdonn printEA(inst); 1144*33318Sdonn } 1145*33318Sdonn 1146*33318Sdonn public jsrop(inst, opcode) 1147*33318Sdonn long inst; 1148*33318Sdonn register String opcode; 1149*33318Sdonn { 1150*33318Sdonn Address startingaddr; /* beginning of jsr instruction */ 1151*33318Sdonn Address retaddr; /* can't call return_addr (frame not set up yet) */ 1152*33318Sdonn 1153*33318Sdonn startingaddr = instaddr - 2; 1154*33318Sdonn switch ((inst >> 3) & 07) { 1155*33318Sdonn case 2: 1156*33318Sdonn retaddr = instaddr; /* two byte instruction */ 1157*33318Sdonn break; 1158*33318Sdonn case 5: 1159*33318Sdonn case 6: 1160*33318Sdonn retaddr = instaddr + 2; /* four byte instruction */ 1161*33318Sdonn break; 1162*33318Sdonn case 7: 1163*33318Sdonn default: 1164*33318Sdonn switch (inst & 07) { 1165*33318Sdonn case 0: 1166*33318Sdonn case 2: 1167*33318Sdonn case 3: 1168*33318Sdonn retaddr = instaddr + 2; 1169*33318Sdonn break; 1170*33318Sdonn case 1: 1171*33318Sdonn default: 1172*33318Sdonn retaddr = instaddr + 4; /* six byte instruction */ 1173*33318Sdonn break; 1174*33318Sdonn } 1175*33318Sdonn break; 1176*33318Sdonn } 1177*33318Sdonn if (printing) { 1178*33318Sdonn printf("\t%s",opcode); 1179*33318Sdonn } 1180*33318Sdonn printEA(inst); 1181*33318Sdonn if (following and followcalls) { 1182*33318Sdonn steppast(startingaddr); 1183*33318Sdonn curfunc = whatblock(pc, true); 1184*33318Sdonn if (not isbperr()) { 1185*33318Sdonn printstatus(); 1186*33318Sdonn /* NOTREACHED */ 1187*33318Sdonn } 1188*33318Sdonn bpact(); 1189*33318Sdonn if (nosource(curfunc) and canskip(curfunc) and nlhdr.nlines != 0) { 1190*33318Sdonn stepto(retaddr); 1191*33318Sdonn instaddr = pc; 1192*33318Sdonn bpact(); 1193*33318Sdonn } else { 1194*33318Sdonn callnews(/* iscall = */ true); 1195*33318Sdonn } 1196*33318Sdonn } 1197*33318Sdonn } 1198*33318Sdonn 1199*33318Sdonn public jmpop(inst, opcode) 1200*33318Sdonn long inst; 1201*33318Sdonn register String opcode; 1202*33318Sdonn { 1203*33318Sdonn Address startingaddr; /* beginning of jump instruction */ 1204*33318Sdonn 1205*33318Sdonn startingaddr = instaddr - 2; 1206*33318Sdonn if (printing) { 1207*33318Sdonn printf("\t%s",opcode); 1208*33318Sdonn } 1209*33318Sdonn printEA(inst); 1210*33318Sdonn if (following) { 1211*33318Sdonn steppast(startingaddr); 1212*33318Sdonn } 1213*33318Sdonn } 1214*33318Sdonn 1215*33318Sdonn public pregmask(mask) 1216*33318Sdonn register int mask; 1217*33318Sdonn { 1218*33318Sdonn register int i; 1219*33318Sdonn register int flag = 0; 1220*33318Sdonn 1221*33318Sdonn if (printing) { 1222*33318Sdonn printf("#<"); 1223*33318Sdonn for (i=0; i<16; i++) { 1224*33318Sdonn if (mask&1) { 1225*33318Sdonn if (flag) { 1226*33318Sdonn printf(","); 1227*33318Sdonn } else { 1228*33318Sdonn ++flag; 1229*33318Sdonn } 1230*33318Sdonn printf("%c%d",(i<8) ? 'd' : 'a', i&07); 1231*33318Sdonn } 1232*33318Sdonn mask >>= 1; 1233*33318Sdonn } 1234*33318Sdonn printf(">"); 1235*33318Sdonn } 1236*33318Sdonn } 1237*33318Sdonn 1238*33318Sdonn public omovem(inst, dummy) 1239*33318Sdonn long inst; 1240*33318Sdonn long dummy; 1241*33318Sdonn { 1242*33318Sdonn register int i, list, mask; 1243*33318Sdonn register int reglist; 1244*33318Sdonn short w; 1245*33318Sdonn 1246*33318Sdonn i = 0; 1247*33318Sdonn list = 0; 1248*33318Sdonn mask = 0100000; 1249*33318Sdonn instread(w); 1250*33318Sdonn reglist = w; 1251*33318Sdonn if ((inst & 070) == 040) { /* predecrement */ 1252*33318Sdonn for (i = 15; i > 0; i -= 2) { 1253*33318Sdonn list |= ((mask & reglist) >> i); 1254*33318Sdonn mask >>= 1; 1255*33318Sdonn } 1256*33318Sdonn for (i = 1; i < 16; i += 2) { 1257*33318Sdonn list |= ((mask & reglist) << i); 1258*33318Sdonn mask >>= 1; 1259*33318Sdonn } 1260*33318Sdonn reglist = list; 1261*33318Sdonn } 1262*33318Sdonn if (printing) { 1263*33318Sdonn printf("\tmovem%c\t",(inst&100)?'l':'w'); 1264*33318Sdonn } 1265*33318Sdonn if (inst&02000) { 1266*33318Sdonn printEA(inst); 1267*33318Sdonn if (printing) { 1268*33318Sdonn printf(","); 1269*33318Sdonn } 1270*33318Sdonn pregmask(reglist); 1271*33318Sdonn } else { 1272*33318Sdonn pregmask(reglist); 1273*33318Sdonn if (printing) { 1274*33318Sdonn printf(","); 1275*33318Sdonn } 1276*33318Sdonn printEA(inst); 1277*33318Sdonn } 1278*33318Sdonn } 1279*33318Sdonn 1280*33318Sdonn public ochk(inst, opcode) 1281*33318Sdonn long inst; 1282*33318Sdonn register String opcode; 1283*33318Sdonn { 1284*33318Sdonn if (printing) { 1285*33318Sdonn printf("\t%s\t", opcode); 1286*33318Sdonn } 1287*33318Sdonn printEA(inst, sizeof(Byte)); 1288*33318Sdonn if (printing) { 1289*33318Sdonn printf(",%c%D", (opcode[0] == 'l') ? 'a' : 'd', (inst>>9)&07); 1290*33318Sdonn } 1291*33318Sdonn } 1292*33318Sdonn 1293*33318Sdonn public soneop(inst, opcode) 1294*33318Sdonn long inst; 1295*33318Sdonn register String opcode; 1296*33318Sdonn { 1297*33318Sdonn register int size; 1298*33318Sdonn 1299*33318Sdonn size = mapsize(inst); 1300*33318Sdonn if (size > 0) { 1301*33318Sdonn if (printing) { 1302*33318Sdonn printf("\t%s%c\t", opcode, suffix(size)); 1303*33318Sdonn } 1304*33318Sdonn printEA(inst); 1305*33318Sdonn } else { 1306*33318Sdonn if (printing) { 1307*33318Sdonn printf("\tbadop"); 1308*33318Sdonn } 1309*33318Sdonn } 1310*33318Sdonn } 1311*33318Sdonn 1312*33318Sdonn public oquick(inst, opcode) 1313*33318Sdonn long inst; 1314*33318Sdonn register String opcode; 1315*33318Sdonn { 1316*33318Sdonn register int size; 1317*33318Sdonn register int data; 1318*33318Sdonn 1319*33318Sdonn size = mapsize(inst); 1320*33318Sdonn data = (int)((inst>>9) & 07); 1321*33318Sdonn if (data == 0) { 1322*33318Sdonn data = 8; 1323*33318Sdonn } 1324*33318Sdonn if (size > 0) { 1325*33318Sdonn if (printing) { 1326*33318Sdonn printf("\t%s%c\t", opcode, suffix(size)); 1327*33318Sdonn printf(IMDF, data); 1328*33318Sdonn printf(","); 1329*33318Sdonn } 1330*33318Sdonn printEA(inst); 1331*33318Sdonn } else { 1332*33318Sdonn if (printing) { 1333*33318Sdonn printf("\tbadop"); 1334*33318Sdonn } 1335*33318Sdonn } 1336*33318Sdonn } 1337*33318Sdonn 1338*33318Sdonn public omoveq(inst, dummy) 1339*33318Sdonn long inst; 1340*33318Sdonn long dummy; 1341*33318Sdonn { 1342*33318Sdonn register int data; 1343*33318Sdonn 1344*33318Sdonn if (printing) { 1345*33318Sdonn data = (int)(inst & 0377); 1346*33318Sdonn if (data > 127) { 1347*33318Sdonn data |= ~0377; 1348*33318Sdonn } 1349*33318Sdonn printf("\tmoveq\t"); 1350*33318Sdonn printf(IMDF, data); 1351*33318Sdonn printf(",d%D", (inst>>9)&07); 1352*33318Sdonn } 1353*33318Sdonn } 1354*33318Sdonn 1355*33318Sdonn public oprint(inst, opcode) 1356*33318Sdonn long inst; 1357*33318Sdonn register String opcode; 1358*33318Sdonn { 1359*33318Sdonn if (printing) { 1360*33318Sdonn printf("\t%s",opcode); 1361*33318Sdonn } 1362*33318Sdonn } 1363*33318Sdonn 1364*33318Sdonn public ostop(inst, opcode) 1365*33318Sdonn long inst; 1366*33318Sdonn register String opcode; 1367*33318Sdonn { 1368*33318Sdonn short w; 1369*33318Sdonn 1370*33318Sdonn instread(w); 1371*33318Sdonn if (printing) { 1372*33318Sdonn printf(opcode, w); 1373*33318Sdonn } 1374*33318Sdonn } 1375*33318Sdonn 1376*33318Sdonn public orts(inst, opcode) 1377*33318Sdonn long inst; 1378*33318Sdonn register String opcode; 1379*33318Sdonn { 1380*33318Sdonn Address addr; 1381*33318Sdonn 1382*33318Sdonn if (following) { 1383*33318Sdonn callnews(/* iscall = */ false); 1384*33318Sdonn if (inst_tracing) { 1385*33318Sdonn addr = currtnaddr(); 1386*33318Sdonn } else { 1387*33318Sdonn addr = return_addr(); 1388*33318Sdonn if (addr == 0) { 1389*33318Sdonn stepto(instaddr - 2); 1390*33318Sdonn addr = currtnaddr(); 1391*33318Sdonn } 1392*33318Sdonn } 1393*33318Sdonn stepto(addr); 1394*33318Sdonn instaddr = pc; 1395*33318Sdonn } 1396*33318Sdonn if (printing) { 1397*33318Sdonn printf("\t%s",opcode); 1398*33318Sdonn } 1399*33318Sdonn } 1400*33318Sdonn 1401*33318Sdonn /* 1402*33318Sdonn * Not used by C compiler; does an rts but before doing so, pops 1403*33318Sdonn * arg bytes from the stack. 1404*33318Sdonn */ 1405*33318Sdonn 1406*33318Sdonn public ortspop(inst, opcode) 1407*33318Sdonn long inst; 1408*33318Sdonn register String opcode; 1409*33318Sdonn { 1410*33318Sdonn Address addr; 1411*33318Sdonn short w; 1412*33318Sdonn 1413*33318Sdonn instread(w); 1414*33318Sdonn if (following) { 1415*33318Sdonn callnews(/* iscall = */ false); 1416*33318Sdonn if (inst_tracing) { 1417*33318Sdonn addr = currtnaddr(); 1418*33318Sdonn } else { 1419*33318Sdonn addr = return_addr(); 1420*33318Sdonn } 1421*33318Sdonn stepto(addr); 1422*33318Sdonn instaddr = pc; 1423*33318Sdonn } 1424*33318Sdonn if (printing) { 1425*33318Sdonn printf(opcode, w); 1426*33318Sdonn } 1427*33318Sdonn } 1428*33318Sdonn 1429*33318Sdonn public omovs(inst, opcode) 1430*33318Sdonn long inst; 1431*33318Sdonn String opcode; 1432*33318Sdonn { 1433*33318Sdonn register int size; 1434*33318Sdonn register unsigned int controlword; 1435*33318Sdonn short w; 1436*33318Sdonn 1437*33318Sdonn size = mapsize(inst); 1438*33318Sdonn instread(w); 1439*33318Sdonn controlword = w >> 11; 1440*33318Sdonn if (printing) { 1441*33318Sdonn printf("\t%s%c\t", opcode, suffix(size)); 1442*33318Sdonn } 1443*33318Sdonn if (controlword & 1){ 1444*33318Sdonn controlword >>= 1; 1445*33318Sdonn if (printing) { 1446*33318Sdonn printf((controlword&0x8) ? "a%D," : "d%D,", controlword&7 ); 1447*33318Sdonn } 1448*33318Sdonn printEA(inst&0xff, size); 1449*33318Sdonn } else { 1450*33318Sdonn controlword >>= 1; 1451*33318Sdonn printEA(inst&0xff, size); 1452*33318Sdonn if (printing) { 1453*33318Sdonn printf((controlword&0x8) ? ",a%D" : ",d%D", controlword&7); 1454*33318Sdonn } 1455*33318Sdonn } 1456*33318Sdonn } 1457*33318Sdonn 1458*33318Sdonn public omovc(inst, opcode) 1459*33318Sdonn long inst; 1460*33318Sdonn String opcode; 1461*33318Sdonn { 1462*33318Sdonn register unsigned int controlword; 1463*33318Sdonn String creg; 1464*33318Sdonn short w; 1465*33318Sdonn 1466*33318Sdonn instread(w); 1467*33318Sdonn if (printing) { 1468*33318Sdonn controlword = w; 1469*33318Sdonn switch (controlword & 0xfff) { 1470*33318Sdonn case 0: 1471*33318Sdonn creg = "sfc"; 1472*33318Sdonn break; 1473*33318Sdonn 1474*33318Sdonn case 1: 1475*33318Sdonn creg = "dfc"; 1476*33318Sdonn break; 1477*33318Sdonn 1478*33318Sdonn case 0x800: 1479*33318Sdonn creg = "usp"; 1480*33318Sdonn break; 1481*33318Sdonn 1482*33318Sdonn case 0x801: 1483*33318Sdonn creg = "vbr"; 1484*33318Sdonn break; 1485*33318Sdonn 1486*33318Sdonn default: 1487*33318Sdonn creg = "???"; 1488*33318Sdonn break; 1489*33318Sdonn } 1490*33318Sdonn controlword >>= 12; 1491*33318Sdonn if (inst & 1){ 1492*33318Sdonn printf((controlword&0x8) ? "%sa%D,%s" : "%sd%D,%s", 1493*33318Sdonn opcode, controlword&7, creg ); 1494*33318Sdonn } else { 1495*33318Sdonn printf((controlword&0x8) ? "%s%s,a%D" : "%s%s,d%D", 1496*33318Sdonn opcode, creg, controlword&7 ); 1497*33318Sdonn } 1498*33318Sdonn } 1499*33318Sdonn } 1500*33318Sdonn 1501*33318Sdonn /* 1502*33318Sdonn * Compute the next address that will be executed from the given one. 1503*33318Sdonn * If "isnext" is true then consider a procedure call as straight line code. 1504*33318Sdonn * 1505*33318Sdonn * Unconditional branches we just follow, for conditional branches 1506*33318Sdonn * we continue execution to the current location and then single step 1507*33318Sdonn * the machine. 1508*33318Sdonn */ 1509*33318Sdonn 1510*33318Sdonn public Address nextaddr(startaddr, isnext) 1511*33318Sdonn Address startaddr; 1512*33318Sdonn Boolean isnext; 1513*33318Sdonn { 1514*33318Sdonn Optab *o; 1515*33318Sdonn short inst; 1516*33318Sdonn 1517*33318Sdonn instaddr = usignal(process); 1518*33318Sdonn if (instaddr == 0 or instaddr == 1) { 1519*33318Sdonn following = true; 1520*33318Sdonn followcalls = (Boolean) (not isnext); 1521*33318Sdonn printing = false; 1522*33318Sdonn iread(&inst, startaddr, sizeof(inst)); 1523*33318Sdonn instaddr = startaddr + sizeof(inst); 1524*33318Sdonn o = decode(inst, startaddr); 1525*33318Sdonn if (o->mask == 0) { 1526*33318Sdonn fprintf(stderr, 1527*33318Sdonn "[internal error: undecodable op at 0x%x]\n", startaddr); 1528*33318Sdonn fflush(stderr); 1529*33318Sdonn } else { 1530*33318Sdonn (*o->opfun)(inst, o->farg); 1531*33318Sdonn } 1532*33318Sdonn following = false; 1533*33318Sdonn } 1534*33318Sdonn return instaddr; 1535*33318Sdonn } 1536*33318Sdonn 1537*33318Sdonn /* 1538*33318Sdonn * Step to the given address and then execute one instruction past it. 1539*33318Sdonn * Set instaddr to the new instruction address. 1540*33318Sdonn */ 1541*33318Sdonn 1542*33318Sdonn private steppast(addr) 1543*33318Sdonn Address addr; 1544*33318Sdonn { 1545*33318Sdonn stepto(addr); 1546*33318Sdonn pstep(process, DEFSIG); 1547*33318Sdonn pc = reg(PROGCTR); 1548*33318Sdonn instaddr = pc; 1549*33318Sdonn } 1550*33318Sdonn 1551*33318Sdonn /* 1552*33318Sdonn * Enter a procedure by creating and executing a call instruction. 1553*33318Sdonn */ 1554*33318Sdonn 1555*33318Sdonn #define CALLSIZE 6 /* size of call instruction */ 1556*33318Sdonn 1557*33318Sdonn public beginproc(p) 1558*33318Sdonn Symbol p; 1559*33318Sdonn { 1560*33318Sdonn char save[CALLSIZE]; 1561*33318Sdonn struct { 1562*33318Sdonn short op; 1563*33318Sdonn char addr[sizeof(long)]; /* unaligned long */ 1564*33318Sdonn } call; 1565*33318Sdonn long dest; 1566*33318Sdonn 1567*33318Sdonn pc = CODESTART + 6; 1568*33318Sdonn iread(save, pc, sizeof(save)); 1569*33318Sdonn call.op = 0x4eb9; /* jsr */ 1570*33318Sdonn dest = codeloc(p) - FUNCOFFSET; 1571*33318Sdonn mov(&dest, call.addr, sizeof(call.addr)); 1572*33318Sdonn iwrite(&call, pc, sizeof(call)); 1573*33318Sdonn setreg(PROGCTR, pc); 1574*33318Sdonn pstep(process, DEFSIG); 1575*33318Sdonn iwrite(save, pc, sizeof(save)); 1576*33318Sdonn pc = reg(PROGCTR); 1577*33318Sdonn if (not isbperr()) { 1578*33318Sdonn printstatus(); 1579*33318Sdonn } 1580*33318Sdonn /* 1581*33318Sdonn * Execute link instruction so the return addr is visible. 1582*33318Sdonn */ 1583*33318Sdonn pstep(process, DEFSIG); 1584*33318Sdonn pc = reg(PROGCTR); 1585*33318Sdonn if (not isbperr()) { 1586*33318Sdonn printstatus(); 1587*33318Sdonn } 1588*33318Sdonn } 1589*33318Sdonn 1590*33318Sdonn /* 1591*33318Sdonn * Special variables for debugging the kernel. 1592*33318Sdonn */ 1593*33318Sdonn 1594*33318Sdonn public integer masterpcbb; 1595*33318Sdonn public integer slr; 1596*33318Sdonn public struct pte *sbr; 1597*33318Sdonn private struct pcb pcb; 1598*33318Sdonn 1599*33318Sdonn public getpcb () 1600*33318Sdonn { 1601*33318Sdonn integer i; 1602*33318Sdonn 1603*33318Sdonn fseek(corefile, masterpcbb & ~0x80000000, 0); 1604*33318Sdonn get(corefile, pcb); 1605*33318Sdonn pcb.pcb_p0lr &= ~AST_CLR; 1606*33318Sdonn printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n", 1607*33318Sdonn pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr 1608*33318Sdonn ); 1609*33318Sdonn # ifdef sun 1610*33318Sdonn for (i = 0; i < 14; i++) { 1611*33318Sdonn setreg(i, pcb.pcb_regs.val[i]); 1612*33318Sdonn } 1613*33318Sdonn # else /* IRIS */ 1614*33318Sdonn for (i = 0; i < 14; i++) { 1615*33318Sdonn setreg(i, pcb.pcb_regs[i]); 1616*33318Sdonn } 1617*33318Sdonn # endif 1618*33318Sdonn } 1619*33318Sdonn 1620*33318Sdonn public copyregs (savreg, reg) 1621*33318Sdonn Word savreg[], reg[]; 1622*33318Sdonn { 1623*33318Sdonn reg[0] = savreg[R0]; 1624*33318Sdonn reg[1] = savreg[R1]; 1625*33318Sdonn reg[2] = savreg[R2]; 1626*33318Sdonn reg[3] = savreg[R3]; 1627*33318Sdonn reg[4] = savreg[R4]; 1628*33318Sdonn reg[5] = savreg[R5]; 1629*33318Sdonn reg[6] = savreg[R6]; 1630*33318Sdonn reg[7] = savreg[R7]; 1631*33318Sdonn reg[8] = savreg[AR0]; 1632*33318Sdonn reg[9] = savreg[AR1]; 1633*33318Sdonn reg[10] = savreg[AR2]; 1634*33318Sdonn reg[11] = savreg[AR3]; 1635*33318Sdonn reg[12] = savreg[AR4]; 1636*33318Sdonn reg[13] = savreg[AR5]; 1637*33318Sdonn reg[14] = savreg[AR6]; 1638*33318Sdonn reg[15] = savreg[AR7]; 1639*33318Sdonn reg[PROGCTR] = savreg[PC]; 1640*33318Sdonn } 1641*33318Sdonn 1642*33318Sdonn /* 1643*33318Sdonn * Map a virtual address to a physical address. 1644*33318Sdonn * XXX THIS CAN'T BE RIGHT... XXX 1645*33318Sdonn */ 1646*33318Sdonn 1647*33318Sdonn public Address vmap (addr) 1648*33318Sdonn Address addr; 1649*33318Sdonn { 1650*33318Sdonn Address r; 1651*33318Sdonn integer v, n; 1652*33318Sdonn struct pte pte; 1653*33318Sdonn 1654*33318Sdonn r = addr & ~0xc0000000; 1655*33318Sdonn v = btop(r); 1656*33318Sdonn switch (addr&0xc0000000) { 1657*33318Sdonn case 0xc0000000: 1658*33318Sdonn case 0x80000000: 1659*33318Sdonn /* 1660*33318Sdonn * In system space, so get system pte. 1661*33318Sdonn * If it is valid or reclaimable then the physical address 1662*33318Sdonn * is the combination of its page number and the page offset 1663*33318Sdonn * of the original address. 1664*33318Sdonn */ 1665*33318Sdonn if (v >= slr) { 1666*33318Sdonn error("address %x out of segment", addr); 1667*33318Sdonn } 1668*33318Sdonn r = ((long) (sbr + v)) & ~0x80000000; 1669*33318Sdonn goto simple; 1670*33318Sdonn 1671*33318Sdonn case 0x40000000: 1672*33318Sdonn /* 1673*33318Sdonn * In p1 space, must not be in shadow region. 1674*33318Sdonn */ 1675*33318Sdonn if (v < pcb.pcb_p1lr) { 1676*33318Sdonn error("address %x out of segment", addr); 1677*33318Sdonn } 1678*33318Sdonn r = (Address) (pcb.pcb_p1br + v); 1679*33318Sdonn break; 1680*33318Sdonn 1681*33318Sdonn case 0x00000000: 1682*33318Sdonn /* 1683*33318Sdonn * In p0 space, must not be off end of region. 1684*33318Sdonn */ 1685*33318Sdonn if (v >= pcb.pcb_p0lr) { 1686*33318Sdonn error("address %x out of segment", addr); 1687*33318Sdonn } 1688*33318Sdonn r = (Address) (pcb.pcb_p0br + v); 1689*33318Sdonn break; 1690*33318Sdonn 1691*33318Sdonn default: 1692*33318Sdonn /* do nothing */ 1693*33318Sdonn break; 1694*33318Sdonn } 1695*33318Sdonn /* 1696*33318Sdonn * For p0/p1 address, user-level page table should be in 1697*33318Sdonn * kernel virtual memory. Do second-level indirect by recursing. 1698*33318Sdonn */ 1699*33318Sdonn if ((r & 0x80000000) == 0) { 1700*33318Sdonn error("bad p0br or p1br in pcb"); 1701*33318Sdonn } 1702*33318Sdonn r = vmap(r); 1703*33318Sdonn simple: 1704*33318Sdonn /* 1705*33318Sdonn * "r" is now the address of the pte of the page 1706*33318Sdonn * we are interested in; get the pte and paste up the physical address. 1707*33318Sdonn */ 1708*33318Sdonn fseek(corefile, r, 0); 1709*33318Sdonn n = fread(&pte, sizeof(pte), 1, corefile); 1710*33318Sdonn if (n != 1) { 1711*33318Sdonn error("page table botch (fread at %x returns %d)", r, n); 1712*33318Sdonn } 1713*33318Sdonn if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) { 1714*33318Sdonn error("page no valid or reclamable"); 1715*33318Sdonn } 1716*33318Sdonn return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum)); 1717*33318Sdonn } 1718*33318Sdonn 1719*33318Sdonn /* 1720*33318Sdonn * Extract a bit field from an integer. 1721*33318Sdonn */ 1722*33318Sdonn 1723*33318Sdonn public integer extractField (s) 1724*33318Sdonn Symbol s; 1725*33318Sdonn { 1726*33318Sdonn integer nbytes, nbits, n, r, off, len; 1727*33318Sdonn 1728*33318Sdonn off = s->symvalue.field.offset; 1729*33318Sdonn len = s->symvalue.field.length; 1730*33318Sdonn nbytes = size(s); 1731*33318Sdonn n = 0; 1732*33318Sdonn if (nbytes > sizeof(n)) { 1733*33318Sdonn printf("[bad size in extractField -- word assumed]\n"); 1734*33318Sdonn nbytes = sizeof(n); 1735*33318Sdonn } 1736*33318Sdonn popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes)); 1737*33318Sdonn nbits = nbytes * BITSPERBYTE; 1738*33318Sdonn r = n >> (nbits - ((off mod nbits) + len)); 1739*33318Sdonn r &= ((1 << len) - 1); 1740*33318Sdonn return r; 1741*33318Sdonn } 1742*33318Sdonn 1743*33318Sdonn /* 1744*33318Sdonn * Change the length of a value in memory according to a given difference 1745*33318Sdonn * in the lengths of its new and old types. 1746*33318Sdonn */ 1747*33318Sdonn 1748*33318Sdonn public loophole (oldlen, newlen) 1749*33318Sdonn integer oldlen, newlen; 1750*33318Sdonn { 1751*33318Sdonn integer i, n; 1752*33318Sdonn Stack *oldsp; 1753*33318Sdonn 1754*33318Sdonn n = newlen - oldlen; 1755*33318Sdonn oldsp = sp - oldlen; 1756*33318Sdonn if (n > 0) { 1757*33318Sdonn for (i = oldlen - 1; i >= 0; i--) { 1758*33318Sdonn oldsp[n + i] = oldsp[i]; 1759*33318Sdonn } 1760*33318Sdonn for (i = 0; i < n; i++) { 1761*33318Sdonn oldsp[i] = '\0'; 1762*33318Sdonn } 1763*33318Sdonn } else { 1764*33318Sdonn for (i = 0; i < newlen; i++) { 1765*33318Sdonn oldsp[i] = oldsp[i - n]; 1766*33318Sdonn } 1767*33318Sdonn } 1768*33318Sdonn sp += n; 1769*33318Sdonn } 1770