#include #include #include #include extern const char *__progname; #define Cisspace(x) isspace((unsigned char)(x)) #define MAXFIELDS 4 typedef enum { FT_N4 = 1, FT_M4, FT_N3, FT_M3, FT_N2, FT_M2, FT_R3, FT_OFF4, FT_OFF8, FT_IMM, FT_DISP8, FT_DISP12 } FIELDTYPE; typedef struct field FIELD; struct field { unsigned short int mask; int shift; int iloc; int ilen; FIELDTYPE type; } ; static char line[128]; static int bitx[16]; static int nbit; static FIELD fields[MAXFIELDS]; static int nfields; static int sext(unsigned int val, unsigned int mask) { if (val & (mask&~(mask>>1))) { return((int)val-(int)mask-1); } else { return(val); } } static void print_instr(void) { int val; int i; int ie; int j; FIELD *f; int ow; val = 0; for (i=32;i<48;i++) { val <<= 1; if (line[i] == '1') val |= 1; } ow = 0; for (ie=23;(ie>=0)&&(line[ie]==' ');ie--) ; if (ie < 0) { fprintf(stderr,"%s: blank instruction\n",__progname); fprintf(stderr,">>> %s",&line[0]); exit(1); } for <"i"> (i=0;i<=ie;) { for (j=nfields-1;j>=0;j--) { f = &fields[j]; if (i == f->iloc) { switch (f->type) { case FT_N4: case FT_M4: case FT_IMM: case FT_R3: ow += printf("%d",(val&f->mask)>>f->shift); break; case FT_N3: case FT_M3: ow += printf("%d",(val&f->mask)>>(f->shift-1)); break; case FT_N2: case FT_M2: ow += printf("%d",(val&f->mask)>>(f->shift-2)); break; case FT_DISP8: case FT_DISP12: ow += printf(".%+d",4+(2*sext((val&f->mask)>>f->shift,f->mask>>f->shift))); break; case FT_OFF4: case FT_OFF8: ow += printf("%d",(val&f->mask)>>f->shift); break; default: abort(); break; } i += f->ilen; continue <"i">; } } putchar(line[i++]); ow ++; } do { putchar(' '); ow ++; } while (ow < 24); printf("%s",&line[24]); } static void count(int x) { if (x < 0) { print_instr(); return; } line[bitx[x]] = '0'; count(x-1); line[bitx[x]] = '1'; count(x-1); } static int find_fields(void) { int i; int ia; FIELD *f; const char *s; int j; int l; void badfield(void) { fprintf(stderr,"%s: bad field\n",__progname); fprintf(stderr,">>> %.*s <> %s",i,&line[0],&line[i]); exit(1); } nfields = 0; for (i=32;i<48;) { f = &fields[nfields]; switch (line[i]) { default: badfield(); break; case '0': case '1': i ++; continue; break; case 'n': if ((i <= 44) && !strncmp(&line[i],"nnnn",4)) { f->type = FT_N4; f->mask = 0xf000 >> (i-32); f->shift = 44 - i; } else if ((i <= 45) && !strncmp(&line[i],"nnn",3)) { f->type = FT_N3; f->mask = 0xe000 >> (i-32); f->shift = 45 - i; } else if ((i <= 46) && !strncmp(&line[i],"nn",2)) { f->type = FT_N2; f->mask = 0xc000 >> (i-32); f->shift = 46 - i; } else { badfield(); } break; case 'm': if ((i <= 44) && !strncmp(&line[i],"mmmm",4)) { f->type = FT_M4; f->mask = 0xf000 >> (i-32); f->shift = 44 - i; } else if ((i <= 45) && !strncmp(&line[i],"mmm",3)) { f->type = FT_M3; f->mask = 0xe000 >> (i-32); f->shift = 45 - i; } else if ((i <= 46) && !strncmp(&line[i],"mm",2)) { f->type = FT_M2; f->mask = 0xc000 >> (i-32); f->shift = 46 - i; } else { badfield(); } break; case 'd': if ((i <= 36) && !strncmp(&line[i],"dddddddddddd",12)) { f->type = FT_DISP12; f->mask = 0xfff0 >> (i-32); f->shift = 36 - i; } else if ((i <= 40) && !strncmp(&line[i],"dddddddd",8)) { f->type = FT_DISP8; f->mask = 0xff00 >> (i-32); f->shift = 40 - i; } else { badfield(); } break; case 'i': if ((i <= 40) && !strncmp(&line[i],"iiiiiiii",8)) { f->type = FT_IMM; f->mask = 0xff00 >> (i-32); f->shift = 40 - i; } else { badfield(); } break; case 'r': if ((i <= 45) && !strncmp(&line[i],"rrr",3)) { f->type = FT_R3; f->mask = 0xe000 >> (i-32); f->shift = 45 - i; } else { badfield(); } break; case 'o': if ((i <= 40) && !strncmp(&line[i],"oooooooo",8)) { f->type = FT_OFF8; f->mask = 0xff00 >> (i-32); f->shift = 40 - i; } else if ((i <= 44) && !strncmp(&line[i],"oooo",4)) { f->type = FT_OFF4; f->mask = 0xf000 >> (i-32); f->shift = 44 - i; } else { badfield(); } break; } switch (f->type) { case FT_N2: case FT_N3: case FT_N4: s = "N"; break; case FT_M2: case FT_M3: case FT_M4: s = "M"; break; case FT_R3: s = "R"; break; case FT_OFF4: case FT_OFF8: s = "off"; break; case FT_IMM: s = "imm"; break; case FT_DISP8: case FT_DISP12: s = "disp"; break; default: abort(); break; } switch (f->type) { case FT_N2: case FT_M2: ia = 2; break; case FT_N3: case FT_M3: case FT_R3: ia = 3; break; case FT_N4: case FT_M4: case FT_OFF4: ia = 4; break; case FT_IMM: case FT_DISP8: case FT_OFF8: ia = 8; break; case FT_DISP12: ia = 12; break; default: abort(); break; } l = strlen(s); do <"found"> { for (j=0;j<24;j++) { if (!strncmp(&line[j],s,l)) { f->iloc = j; f->ilen = l; break <"found">; } } fprintf(stderr,"%s: field %.*s but no %s found\n",__progname,ia,&line[i],s); fprintf(stderr,">>> %s",&line[0]); exit(1); } while (0); i += ia; nfields ++; } return(0); } int main(void); int main(void) { int i; while (fgets(&line[0],sizeof(line)-1,stdin)) { nbit = 0; if (strlen(line) < 48) continue; if ((line[29] != ' ') || (line[30] != ' ') || (line[31] != ' ')) continue; if (find_fields()) continue; for (i=32;line[i]&&(i<48);i++) { if ((line[i] != '0') && (line[i] != '1') && !Cisspace(line[i])) { bitx[nbit++] = i; } } count(nbit-1); } return(0); }