/* * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. * * This product is part of the Amsterdam Compiler Kit. * * Permission to use, sell, duplicate or disclose this software must be * obtained in writing. Requests for such permissions may be sent to * * Dr. Andrew S. Tanenbaum * Wiskundig Seminarium * Vrije Universiteit * Postbox 7161 * 1007 MC Amsterdam * The Netherlands * */ #ifndef NORCSID static char rcsid[] = "$Header$"; #endif /* * Decode compact EM assembly language * * Author: Johan Stevenson, Vrije Universiteit, Amsterdam */ #include #include #include #include #include #include #include #include #define get8() ((unsigned)getchar()) #define check(x) if (!(x)) fail_check() #define MAXSTR 256 /* * global variables */ int opcode; int offtyp; long argval; int dlbval; char string[MAXSTR]; int strsiz; int wsize; int psize; int lineno; int argnum; int errors; char *progname; char *filename; long wordmask[] = { /* allowed bits in a word */ 0x00000000, 0x000000FF, 0x0000FFFF, 0x00000000, 0xFFFFFFFF }; long sizemask[] = { /* allowed bits in multiples of 'wsize' */ 0x00000000, 0x7FFFFFFF, 0x7FFFFFFE, 0x00000000, 0x7FFFFFFC }; /* * external tables */ extern char em_flag[]; extern short em_ptyp[]; extern char em_mnem[][4]; extern char em_pseu[][4]; /* * routines */ int get16(); long get32(); main(argc,argv) char **argv; { progname = argv[0]; if (argc >= 2) { filename = argv[1]; if (freopen(argv[1],"r",stdin) == NULL) fatal("can't open %s",argv[1]); } if (argc >= 3) if (freopen(argv[2],"w",stdout) == NULL) fatal("can't create %s",argv[2]); if (get16() != sp_magic) fatal("bad magic word"); /* In System III the array is called _ctype[] without the trailing '_' */ (_ctype_+1)['_'] = (_ctype_+1)['a']; while (nextline()) ; return(errors ? -1 : 0); } /* ----- copy ----- */ int nextline() { register t; lineno++; argnum = 1; switch (t = table1()) { case EOF: return(0); case sp_fmnem: instr(); break; case sp_fpseu: pseudo(); break; case sp_ilb1: case sp_ilb2: argnum = 0; putarg(sp_cst2); break; case sp_dlb1: case sp_dlb2: case sp_dnam: argnum = 0; putarg(t); break; default: error("unknown opcode %d",t); } putchar('\n'); return(1); } instr() { register i,j,t; register long l; i = opcode - sp_fmnem; printf(" %s",em_mnem[i]); j = em_flag[i] & EM_PAR; if (j == PAR_NO) return; t = em_ptyp[j]; t = getarg(t); /* * range checking */ switch (j) { case PAR_N: check(argval >= 0); break; case PAR_G: if (t != sp_cst2 && t != sp_cst4) break; check(argval >= 0); /* fall through */ case PAR_L: l = argval >= 0 ? argval : -argval; check((l & ~wordmask[psize]) == 0); break; case PAR_W: if (t == sp_cend) break; check((argval & ~wordmask[wsize]) == 0); /* fall through */ case PAR_S: check(argval != 0); /* fall through */ case PAR_Z: check((argval & ~sizemask[wsize]) == 0); break; case PAR_O: check(argval != 0); check((argval & ~sizemask[wsize])==0 || (wsize % argval)==0); break; case PAR_B: t = sp_ilb2; break; case PAR_R: check(argval >= 0 && argval <= 2); break; } putarg(t); } pseudo() { register i,t; i = opcode; printf(" %s",em_pseu[i - sp_fpseu]); switch (i) { case ps_bss: case ps_hol: putarg(getarg(cst_ptyp)); putarg(getarg(val_ptyp)); putarg(getarg(ptyp(sp_cst2))); check(argval==0 || argval==1); break; case ps_rom: case ps_con: putarg(getarg(val_ptyp)); while ((t = getarg(any_ptyp)) != sp_cend) putarg(t); break; case ps_mes: putarg(getarg(ptyp(sp_cst2))); if (argval == ms_emx) { putarg(getarg(ptyp(sp_cst2))); check(argval > 0 && argval <= 4); wsize = (int) argval; putarg(getarg(ptyp(sp_cst2))); check(argval > 0 && argval <= 4); psize = (int) argval; } while ((t = getarg(any_ptyp)) != sp_cend) putarg(t); break; case ps_exa: case ps_ina: putarg(getarg(sym_ptyp)); break; case ps_exp: case ps_inp: putarg(getarg(ptyp(sp_pnam))); break; case ps_exc: putarg(getarg(ptyp(sp_cst2))); putarg(getarg(ptyp(sp_cst2))); break; case ps_pro: putarg(getarg(ptyp(sp_pnam))); putarg(getarg(cst_ptyp|ptyp(sp_cend))); break; case ps_end: putarg(getarg(cst_ptyp|ptyp(sp_cend))); break; default: error("bad pseudo %d",i); } } /* ----- input ----- */ int getarg(typset) { register t,argtyp; argtyp = t = table2(); if (t == EOF) fatal("unexpected EOF"); t -= sp_fspec; assert(t >= 0 && t < 16); t = 1 << t; if ((typset & t) == 0) error("bad argument type %d",argtyp); return(argtyp); } int table1() { register i; i = get8(); if (i < sp_fmnem+sp_nmnem && i >= sp_fmnem) { opcode = i; return(sp_fmnem); } if (i < sp_fpseu+sp_npseu && i >= sp_fpseu) { opcode = i; return(sp_fpseu); } if (i < sp_filb0+sp_nilb0 && i >= sp_filb0) { argval = i - sp_filb0; return(sp_ilb2); } return(table3(i)); } int table2() { register i; i = get8(); if (i < sp_fcst0+sp_ncst0 && i >= sp_fcst0) { argval = i - sp_zcst0; return(sp_cst2); } return(table3(i)); } int table3(i) { long consiz; switch(i) { case sp_ilb1: argval = get8(); break; case sp_dlb1: dlbval = get8(); break; case sp_dlb2: dlbval = get16(); if ( dlbval<0 ) { error("illegal data label .%d",dlbval); dlbval=0 ; } break; case sp_cst2: argval = get16(); break; case sp_ilb2: argval = get16(); if ( argval<0 ) { error("illegal instruction label %D",argval); argval=0 ; } break; case sp_cst4: argval = get32(); break; case sp_dnam: case sp_pnam: getstring(1); break; case sp_scon: getstring(0); break; case sp_doff: offtyp = getarg(sym_ptyp); getarg(cst_ptyp); break; case sp_icon: case sp_ucon: case sp_fcon: getarg(cst_ptyp); consiz = (long) argval; getstring(0); argval = consiz; break; } return(i); } int get16() { register int l_byte, h_byte; l_byte = get8(); h_byte = get8(); if ( h_byte>=128 ) h_byte -= 256 ; return l_byte | (h_byte*256) ; } long get32() { register long l; register int h_byte; l = get8(); l |= (unsigned)get8()*256 ; l |= get8()*256L*256L ; h_byte = get8() ; if ( h_byte>=128 ) h_byte -= 256 ; return l | (h_byte*256L*256*256L) ; } getstring(ident) { register char *p; register n; getarg(cst_ptyp); if (argval < 0 || argval > MAXSTR) fatal("string/identifier too long"); strsiz = n = argval; p = string; while (--n >= 0) *p++ = get8(); if (ident) { if (!isascii(string[0]) || !isalpha(string[0])) { identerror(); return; } for (n=strsiz,p=string+1;--n>0;p++) if (!isascii(*p) || !isalnum(*p)) { identerror(); return; } } } /* ----- output ----- */ putarg(t) { if (argnum != 0) putchar(argnum == 1 ? ' ' : ','); argnum++; puttyp(t); } puttyp(t) { switch (t) { case sp_ilb1: case sp_ilb2: printf("*%d",(int) argval); break; case sp_dlb1: case sp_dlb2: printf(".%d",dlbval); break; case sp_dnam: putstr(0,0); break; case sp_cst2: case sp_cst4: printf("%D",argval); break; case sp_doff: puttyp(offtyp); if (argval >= 0) putchar('+'); printf("%D",argval); break; case sp_pnam: putstr('$',0); break; case sp_scon: putstr('\'','\''); break; case sp_icon: putstr(0,'I'); printf("%D",argval); break; case sp_ucon: putstr(0,'U'); printf("%D",argval); break; case sp_fcon: putstr(0,'F'); printf("%D",argval); break; case sp_cend: putchar('?'); break; } } putstr(c,c2) register c; { register char *p; if (c) putchar(c); p = string; while (--strsiz >= 0) { c = *p++ & 0377; if (c >= 040 && c < 0177) { if (c == '\'' || c == '\\') putchar('\\'); putchar(c); } else printf("\\%03o",c); } if (c2) putchar(c2); } /* ----- error handling ----- */ fail_check() { error("argument range error"); } identerror() { error("'%s' is not a correct identifier",string); } /* VARARGS */ error(s,a1,a2,a3,a4) char *s; { fprintf(stderr, "%s: line %d: ", filename ? filename : progname, lineno); fprintf(stderr,s,a1,a2,a3,a4); fprintf(stderr,"\n"); errors++; } /* VARARGS */ fatal(s,a1,a2,a3,a4) char *s; { error(s,a1,a2,a3,a4); exit(-1); }