/* * instruction decoding * VAX instructions; works only on a VAX for now */ #include "defs.h" #include "space.h" #define LOBYTE 0377 /* instruction printing */ /* * Argument access types */ #define ACCA (8<<3) /* address only */ #define ACCR (1<<3) /* read */ #define ACCW (2<<3) /* write */ #define ACCM (3<<3) /* modify */ #define ACCB (4<<3) /* branch displacement */ #define ACCI (5<<3) /* XFC code */ /* * Argument data types */ #define TYPB 0 /* byte */ #define TYPW 1 /* word */ #define TYPL 2 /* long */ #define TYPQ 3 /* quad */ #define TYPF 4 /* floating */ #define TYPD 5 /* double floating */ typedef struct optab *OPTAB; struct optab { char *iname; char val; char nargs; char argtype[6]; } optab[]; struct optab junkoptab = {"???"}; char *regname[]; char *fltimm[]; static ADDR incp; short ioptab[256]; /* index by opcode to optab */ mkioptab() {/* set up ioptab */ register OPTAB p=optab; register int i; for (i = 0; i < 256; i++) ioptab[i] = -1; /* flag invalid */ while (p->iname){ ioptab[p->val&LOBYTE]=p-optab; p++; } } printins(idsp) { register short argno; /* argument index */ register short mode; /* mode */ register char **r; /* register name */ register unsigned char ins; long d; /* assembled byte, word, long or float */ long snarf(); register char * ap; register OPTAB ip; ins = cget(dot, idsp); chkerr(); if (ioptab[ins] == -1) ip = &junkoptab; else ip = &optab[ioptab[ins]]; printf("%s%8t",ip->iname); incp = 1; ap = ip->argtype; for (argno=0; argno<ip->nargs; argno++,ap++) { var[argno] = 0x80000000; if (argno!=0) printc(','); top: if (*ap&ACCB) mode = 0xAF + ((*ap&7)<<5); /* branch displacement */ else{ mode = cget(inkdot((WORD)incp), idsp); chkerr(); ++incp; } if (mode & 0300) {/* not short literal */ r = ®name[mode&0xF]; mode >>= 4; switch ((int)mode) { case 4: /* [r] */ printf("[%s]",*r); goto top; case 5: /* r */ printf("%s",*r); break; case 6: /* (r) */ printf("(%s)",*r); break; case 7: /* -(r) */ printf("-(%s)",*r); break; case 9: /* *(r)+ */ printc('*'); case 8: /* (r)+ */ if (r==(regname+0xF)) { printc('$'); if (mode==9){ /* PC absolute, always 4 bytes*/ d = snarf(4, idsp); goto disp; } switch(*ap&7){ case TYPB: d = snarf(1, idsp); goto disp; case TYPW: d = snarf(2, idsp); goto disp; case TYPL: d = snarf(4, idsp); goto disp; case TYPQ: d = snarf(4, idsp); printquad(d, snarf(4, idsp)); break; case TYPF: printfloating(snarf(4, idsp), 0L); break; case TYPD: d = snarf(4, idsp); printfloating(d, snarf(4, idsp)); break; } /*end of type switch */ /* * here only for TYPQ, TYPf, TYPD * others went to disp */ } else { /*it's not PC immediate or abs*/ printf("(%s)+",*r); } break; case 0xB: /* byte displacement defferred*/ printc('*'); case 0xA: /* byte displacement */ d = snarf(1, idsp); goto disp; case 0xD: /* word displacement deferred */ printc('*'); case 0xC: /* word displacement */ d = snarf(2, idsp); goto disp; case 0xF: /* long displacement deferred */ printc('*'); case 0xE: /* long displacement */ d = snarf(4, idsp); goto disp; disp: var[argno]=d; if (r==(regname+0xF) && mode>=0xA){ /* PC offset addressing */ var[argno] += dot+incp; } psymoff(var[argno],ANYSP,""); if (r != regname+0xF) printf("(%s)",*r); break; } /* end of the mode switch */ } else { /* short literal */ var[argno]=mode; if((*ap&7)==TYPF || (*ap&7)==TYPD) printf("$%s",fltimm[mode]); else printf("$%r",mode); } } if (ins==0xCF || ins==0xAF || ins==0x8F) {/* CASEx instr */ for (argno=0; argno<=var[2]; ++argno) { printc(EOR); printf(" %R: ",argno+var[1]); d=sget(inkdot((WORD)incp+argno+argno),idsp); if (d&0x8000) d -= 0x10000; psymoff((WORD)(inkdot((WORD)incp)+d),ANYSP,""); } incp += var[2]+var[2]+2; } dotinc=incp; } /* * 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}; static long snarf(nbytes, idsp) int nbytes; { register int byteindex; union Long{ char long_bytes[4]; long long_value; } d; d.long_value = 0; for (byteindex = 0; byteindex < nbytes; byteindex++){ d.long_bytes[byteindex] = cget(inkdot((WORD)incp), idsp); chkerr(); ++incp; } if (d.long_value & magic_masks[nbytes]) d.long_value -= magic_compl[nbytes]; return(d.long_value); } static printfloating(word_first, word_last) long word_first; long word_last; { union Double{ struct { long word_first; long word_last; } composite; double dvalue; } reconstructed; reconstructed.composite.word_first = word_first; reconstructed.composite.word_last = word_last; fpout('F', (char *)&reconstructed.dvalue); } static printquad(word_first, word_last) long word_first; long word_last; { union Quad { char quad_bytes[8]; long quad_long[2]; } reconstructed; int leading_zero = 1; int byteindex; int nibbleindex; register int ch; reconstructed.quad_long[0] = word_first; reconstructed.quad_long[1] = word_last; for (byteindex = 7; byteindex >= 0; --byteindex){ for (nibbleindex = 4; nibbleindex >= 0; nibbleindex -= 4){ ch = (reconstructed.quad_bytes[byteindex] >> nibbleindex) & 0x0F; if ( ! (leading_zero &= (ch == 0) ) ){ if (ch <= 0x09) printc(ch + '0'); else printc(ch - 0x0A + 'a'); } } } }