#ifndef lint static char sccsid[] = "@(#)opset.c 4.2 10/27/82"; #endif lint /* * UNIX debugger * Instruction printing routines. * MACHINE DEPENDENT */ #ifdef ADB #include "defs.h" #endif ADB #ifdef SDB #include "head.h" #endif SDB L_INT dot; INT dotinc; L_INT insoutvar[36]; #ifdef ADB L_INT var[36]; #endif ADB #undef INSTTAB #include "instrs.h" STRING regname[]; STRING fltimm[]; POS type, space, incp; /* * Definitions for registers and for operand classes */ char *insregname(); /* how to print a register */ #define R_PC 0xF #define OC_IMM0 0x0 #define OC_IMM1 0x1 #define OC_IMM2 0x2 #define OC_IMM3 0x3 #define OC_INDEX 0x4 #define OC_REG 0x5 #define OC_DREG 0x6 #define OC_ADREG 0x7 #define OC_AIREG 0x8 #define OC_DAIREG 0x9 #define OC_BDISP 0xA #define OC_DBDISP 0xB #define OC_WDISP 0xC #define OC_DWDISP 0xD #define OC_LDISP 0xE #define OC_DLDISP 0xF #define OC_SHIFT 4 #define OC_CONS(oc,reg) (((oc & 0xF) << OC_SHIFT) | (reg & 0xF)) #define OC_AMEXT(x) (((x) >> OC_SHIFT) & 0xF) #define OC_REGEXT(x) ((x) & 0xF) /* * Definitions for large numbers */ #include "asnumber.h" typedef struct as_number *numberp; numberp snarf(); numberp snarfreloc(); /* * Definitions for special instructions */ #define CASEB 0x8F #define CASEW 0xAF #define CASEL 0xCF /* * Definitions for converting TYP's into numbers, booleans, etc. * These are shared with the assembler. */ extern int ty_NORELOC[]; extern int ty_float[]; extern int ty_nbyte[]; extern int ty_nlg[]; extern char *ty_string[]; short ioptab[3][256]; /* two level index by opcode into insttab */ int mapescbyte(byte) u_char byte; { switch(byte){ default: return(0); case ESCD: return(1); case ESCF: return(2); } } mkioptab() { REG struct insttab *p; int mapchar; for(p = insttab; p->iname; p++){ mapchar = mapescbyte(p->eopcode); if (ioptab[mapchar][p->popcode]) continue; ioptab[mapchar][p->popcode] = p - insttab; } } u_char snarfuchar(); /* * Global variables for communicating with the minions and printins */ static int idsp; static short argno; /* which argument one is working on */ static char insoutfmt[2]; /* how to format the relocated symbols */ #ifdef SDB static struct proct *procp; #endif SDB static savevar(val) long val; { var[argno] = val; insoutvar[argno] = val; } printins(fmt, Idsp, ins) char fmt; #ifndef vax u_char ins; #else u_char ins; #endif int Idsp; { u_char mode; /* mode */ u_char ins2; char *indexreg; /* print of which register indexes */ char *indexed; /* we indexed */ char *operandout(); REG u_char *ap; REG struct insttab *ip; u_char optype; int mapchar; idsp = Idsp; type = DSYM; space = idsp; #ifdef SDB procp = adrtoprocp(dot); if (procp->paddr == dot){ printf("0x%04.4x", ins); incp = 2; goto ret; } #endif SDB #ifdef ADB insoutfmt[0] = 0; #endif ADB #ifdef SDB insoutfmt[0] = fmt; #endif SDB incp = 1; if ((mapchar = mapescbyte(ins)) != 0){ ins2 = snarfuchar(); if (ioptab[mapchar][ins2] == 0){ /* * Oops; not a defined instruction; * back over this escape byte. */ incp -= 1; mapchar = 0; } else { ins = ins2; } } if (ioptab[mapchar][ins] == 0){ printf(": %x", ins); goto ret; } ip = &insttab[ioptab[mapchar][ins]]; printf("%s\t", ip->iname); for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) { savevar(0x80000000); /* an illegal symbol */ optype = *ap; if (argno != 0) printc(','); indexreg = 0; indexed = 0; do{ if (A_ACCEXT(optype) & ACCB){ switch(A_TYPEXT(optype)){ case TYPB: mode = OC_CONS(OC_BDISP, R_PC); break; case TYPW: mode = OC_CONS(OC_WDISP, R_PC); break; } } else { mode = snarfuchar(); } indexreg = operandout(mode, optype); if (indexed) printf("[%s]", indexed); indexed = indexreg; } while(indexed); } if (mapchar == 0){ switch(ins){ case CASEB: case CASEW: case CASEL: casebody(insoutvar[1], insoutvar[2]); break; default: break; } } ret: ; #ifdef SDB oincr = incp; #endif SDB #ifdef ADB dotinc = incp; #endif ADB } casebody(base, limit) long base; long limit; { int i; POS baseincp; POS advincp; struct as_number *valuep; #define OSIZE (sizeof(short)) argno = 0; baseincp = incp; for (i = 0; i <= limit; i++) { printc(EOR); #ifdef SDB printf(" %d: ", i + base); #endif SDB #ifdef ADB printf(" %R: ", i + base); #endif ADB valuep = snarfreloc(OSIZE, 0); advincp = incp; incp = baseincp; dispaddress(valuep, OC_CONS(OC_WDISP, R_PC)); incp = advincp; } } /* * magic values to mung an offset to a register into * something that psymoff can understand.. all magic */ /* 0 1 2 3 4 */ static long magic_masks[5] = {0, 0x80, 0x8000, 0, 0}; static long magic_compl[5] = {0, 0x100, 0x10000,0, 0}; /* * Snarf up some bytes, and put in the magic relocation flags */ numberp snarfreloc(nbytes) int nbytes; { numberp back; back = snarf(nbytes); if (back->num_ulong[0] & magic_masks[nbytes]) back->num_ulong[0] -= magic_compl[nbytes]; return(back); } /* * The following code is NOT portable from the PDP 11 to the VAX * because of the byte ordering problem. */ numberp snarf(nbytes) int nbytes; { REG int i; static struct as_number backnumber; static struct as_number znumber; /* init'ed to 0 */ backnumber = znumber; for (i = 0; i < nbytes; i++) backnumber.num_uchar[i] = snarfuchar(); return(&backnumber); } /* * Read one single character, and advance the dot */ u_char snarfuchar() { u_char back; /* * assert: bchkget and inkdot don't have side effects */ back = (u_char)bchkget(inkdot(incp), idsp); incp += 1; return(back); } /* * normal operand; return non zero pointer to register * name if this is an index instruction. */ char *operandout(mode, optype) u_char mode; u_char optype; { char *r; int regnumber; int nbytes; regnumber = OC_REGEXT(mode); r = insregname(regnumber); switch (OC_AMEXT(mode)){ case OC_IMM0: case OC_IMM1: case OC_IMM2: case OC_IMM3: shortliteral(mode, optype); return(0); case OC_INDEX: return(r); /* will be printed later */ case OC_REG: printf("%s", r); return(0); case OC_DREG: printf("(%s)", r); return(0); case OC_ADREG: printf("-(%s)", r); return(0); case OC_DAIREG: printc('*'); case OC_AIREG: if (regnumber == R_PC){ pcimmediate(mode, optype); } else { printf("(%s)+", r); } return(0); case OC_DBDISP: printc('*'); case OC_BDISP: nbytes = 1; break; case OC_DWDISP: printc('*'); case OC_WDISP: nbytes = 2; break; case OC_DLDISP: printc('*'); case OC_LDISP: nbytes = 4; break; } dispaddress(snarfreloc(nbytes), mode); return(0); } dispaddress(valuep, mode) numberp valuep; u_char mode; { int regnumber = OC_REGEXT(mode); switch(OC_AMEXT(mode)){ case OC_BDISP: case OC_DBDISP: case OC_WDISP: case OC_DWDISP: case OC_LDISP: case OC_DLDISP: if (regnumber == R_PC){ /* PC offset addressing */ valuep->num_ulong[0] += inkdot(incp); } } #ifdef ADB psymoff(valuep->num_ulong[0], type, &insoutfmt[0]); if (regnumber != R_PC){ /* } */ #endif ADB #ifdef SDB if(psymoff(valuep->num_ulong[0], regnumber, &insoutfmt[0]) && (regnumber != R_PC)){ #endif SDB printf("(%s)", insregname(regnumber)); } savevar((long)valuep->num_ulong[0]); } /* * get a register name */ char *insregname(regnumber) int regnumber; { char *r; r = regname[regnumber]; #ifdef SDB if ( (insoutfmt[0] == 'i') && (regnumber >= 6) && (regnumber <= 11) && (adrtoregvar(regnumber, procp) != -1)) { r = sl_name; } #endif SDB return(r); } /* * print out a short literal */ shortliteral(mode, optype) u_char mode; u_char optype; { savevar((long)mode); switch(A_TYPEXT(optype)){ case TYPF: case TYPD: case TYPG: case TYPH: printf("$%s", fltimm[mode]); break; default: #ifdef ADB printf("$%r", mode); #endif ADB #ifdef SDB printf("$%d", mode); #endif SDB break; } } pcimmediate(mode, optype) u_char mode; u_char optype; { int nbytes; printc('$'); if (mode == OC_DAIREG){ /* PC absolute, always 4 bytes*/ dispaddress(snarfreloc(4), mode); return; } nbytes = ty_nbyte[A_TYPEXT(optype)]; if (! ty_NORELOC[A_TYPEXT(optype)]){ dispaddress(snarfreloc(nbytes), mode); return; } bignumprint(nbytes, optype); } bignumprint(nbytes, optype) int nbytes; u_char optype; { numberp valuep; int leading_zero = 1; REG int bindex; REG int nindex; REG int ch; valuep = snarf(nbytes); switch(A_TYPEXT(optype)){ case TYPF: printf("0f%f", valuep->num_num.numFf_float.Ff_value); break; case TYPD: printf("0d%f", valuep->num_num.numFd_float.Fd_value); break; case TYPG: printf("0g::"); goto qprint; case TYPH: printf("0h::"); goto qprint; case TYPQ: case TYPO: qprint: for (bindex = nbytes - 1; bindex >= 0; --bindex){ for (nindex = 4; nindex >= 0; nindex -= 4){ ch = (valuep->num_uchar[bindex] >> nindex); ch &= 0x0F; if ( ! (leading_zero &= (ch == 0) ) ){ if (ch <= 0x09) printc(ch + '0'); else printc(ch - 0x0A + 'a'); } } } break; } } #ifdef SDB L_INT inkdot(incr) int incr; { L_INT newdot; newdot = dot + incr; return(newdot); } printc(c) char c; { printf("%c", c); } psymoff(v, regnumber, fmt) L_INT v; char *fmt; { struct proct *procp; REG int diff; if (fmt[0] == 'i') { switch(regnumber){ case 12: /* parameter */ if ((diff = adrtoparam((ADDR) v, adrtoprocp(dot))) != -1) { printf("%s", sl_name); prdiff(diff); return(0); } break; case 13: /* local */ if ((diff = adrtolocal((ADDR) -v, adrtoprocp(dot)) ) != -1) { printf("%s", sl_name); prdiff(diff); return(0); } break; default: break; } if (v < firstdata) { if ((procp = adrtoprocp((ADDR) v)) != badproc) { prlnoff(procp, v); return(0); } } else { if ((diff = adrtoext((ADDR) v)) != -1) { printf("%s", sl_name); prdiff(diff); return(0); } } } prhex(v); return(1); } prdiff(diff) { if (diff) { printf("+"); prhex(diff); } } #endif SDB