/* ** mit.c -- machine instruction table functions ** ** mitndx[] mitptr[] mitnxt[] ** _____ _____ _____ ** |__|__| |__|__| |__|__| ** |__|__| |__|__| |__|__|<-+ ** hash -> |__|__| -> |__|__| |__|__| | ** |__|__| |__|__| |__|__|--+ ** |__|__| |__|__| |__|__| ** | ** v ** mnemonic variant.. ** __ | ** |__|...00 vlen optr fmt obj... ** __ _____ _____ __ ** format bits (<-) |__| |__|__| |__|__| |__|... ** 3-bit instr length (-1) | ** field types v ** 0 = obj byte operand pattern ** 001 = 8-bit expr __ ** 011 = 8-bit pc rel expr | |...00 ** 101 = 16-bit expr -- ** 111 = 16-bit pc rel expr ** */ #include #include "mac.h" /* must be included first */ /* #define NOCCARGC */ int opadj, /* operation code adjustment */ hashval; /* global hash value for speed */ char expbuf[MAXLINE]; /* buffer for operand expressions */ extern int mitable, /* machine instruction table (size) */ mitndx[], /* mit indices ( hash -> which */ mitnxt[], /* mit synonym chain */ mitptr[]; /* mnemonic syntax ptrs */ extern char mitbuf; /* instruction syntax buffer */ extern int looks; /* number of looks to find it */ hash(ptr, cnt) char *ptr; int cnt; { /* calculate hash value */ hashval = 0; while(*ptr > ' ' && atend(*ptr) == 0) hashval = (hashval << 1) + toupper(*ptr++); return (hashval % cnt); } find(inst) char *inst; { /* search for instr in mit */ char *mit; int h, ndx; looks = 0; ndx = mitndx[h = hash(inst, MICOUNT)]; /* calc hash index */ while(ndx != EOF) { ++looks; if(fldcmp(inst, mit = mitptr[ndx]) == 0) { /* mnemonic matches */ inst = skip(2, inst); /* instr operand field */ mit += strlen(mit) + 1; /* first variant */ while(*mit++) { /* another variant? */ ++looks; if(match(inst, getint(mit))) return (mit); mit += *(mit - 1); /* next variant */ } return (0); } if((h = mitnxt[h]) == EOF) return (0); ndx = mitndx[h]; } return (0); } match(inst, mit) char *inst, *mit; { /* match operands to mit */ char *backup, *exp; int nest; opadj = 0; backup = inst; if(mit == 0) { if(atend(*inst)) return (YES); return (NO); } exp = expbuf; /* init expr buffer */ while(YES) { while(isspace(*inst)) ++inst; while(isspace(*mit)) ++mit; if(atend(*inst)) { if(atend(*mit) || *mit == ANOTHER) return (YES); goto next; } if(atend(*mit)) return (NO); if(islower(*mit)) { /* expression */ ++mit; /* bump past x or y */ nest = 0; while(!atend(*inst)) { /* bypass expression */ if(*inst == ',') break; if(*inst == ')' && nest == 0) break; switch(*inst) { case '(': ++nest; break; case ')': --nest; } *exp++ = *inst++; /* extract expressions */ } *exp++ = ','; *exp = NULL; /* terminate expression */ continue; } if(lexorder(*inst++, *mit++)) { next: while(*mit) { if(*mit == ANOTHER) { /* end of syntax for this try */ ++opadj; /* bump opcode adjustment */ ++mit; inst = backup; /* setup next try */ exp = expbuf; /* reset expr buffer pointer */ break; } ++mit; } if(atend(*mit)) return (NO); } } }