/* variables globales */ # define MAXMAC 2000 # define MAXMEM 20000 # define MAXPAR 20 # include struct stligne { char *etiquette; char *codop; char *paramv [MAXPAR]; }; struct descripm { char *nom; char *corps; }; struct descripm pmac [MAXMAC]; struct descripm *entc = pmac; char *ptc, *pts; char *index(); char mem [MAXMEM]; char *memp = mem; char *salloc (); /* allocation dynamique de la mem. pour stocker le corps d'une macro */ putmacro (c) { if (memp >= MAXMEM + mem) nonmem (); *memp++ = c; } /* fonction delimitant un champ */ char *champ () { char *ptd = pts; while (*ptc != '\n') { switch (*ptc) { case '<': while (*++ptc!='>' && *ptc!='') *pts++ = *ptc; ++ptc; break; case '\t': case ' ': /* remplacer les blancs et les tabulation par des 0 */ *pts++ = ''; while (*++ptc == ' ' || *ptc == '\t') ; return (ptd); default: *pts++ = *ptc++; } } *pts++ = ''; return (ptd); } /* decomposition dune ligne en champs */ decompligne(ligne, tchampp, copie) char *ligne, *copie; struct stligne *tchampp; { int i; char *pit; char *pat; ptc = ligne; pts = copie; tchampp->etiquette = champ (); tchampp->codop = champ (); pit = champ (); /* detecter les . argumens */ if (pat = index(tchampp->codop, '.')) { tchampp->paramv[0] = pat + 1; *pat = ''; } else tchampp->paramv[0] = ""; for (i = 1; i < MAXPAR; i++) /* remplacer les , par des */ { tchampp->paramv[i] = pit; while (*pit != ',' && *pit != '') pit++; if (*pit == ',') *pit++ = ''; } } /* fonction recherchant le nom d'une macro dans le descrip. des macros */ struct descripm *ismacro (tchampp) struct stligne *tchampp; { struct descripm *macp; for (macp = pmac; macp < entc; macp++) { if (strcmp (tchampp->codop, macp->nom) == 0) return (macp); } return (NULL); } /* message d'erreur pour signaler des parametres de macro incorrects */ merr () { fprintf (stderr, "parametre incorrect \n"); exit (1); } /* teste s'il y a au moins un \@, le remplace par l'etiq. courante */ getetiq (macp) struct descripm *macp; { static int etiqcount; char c; char *car; car = macp->corps; while ((c = *car) != '') { if ((c = *car++) == '\') { if ((c = *car++) == '@') return (++etiqcount); } } return (0); } expandmacro (macp, tchampp) /* remplace le nom d'une macro par son corps */ struct descripm *macp; struct stligne *tchampp; { char c, ligne[120], *chaine; int dansif; char *corps; int etiq; corps = macp->corps; etiq = getetiq (macp); chaine = ligne; dansif = 0; if (*tchampp->etiquette) printf("%s\t", tchampp->etiquette); while ((c = *corps) != '') { if ((c = *corps++) == '\') /* remplacer le nom des parametres par leur valeur */ { if ((c = *corps) >= '0' && c <= '9') { sprintf(chaine, "%s", tchampp->paramv[c-'0']); chaine += strlen(chaine); } else if ((c = *corps) == '@' ) { /* remplacer les \@ par l'etiquette courante */ sprintf(chaine, ".%d", etiq); chaine += strlen(chaine); } else merr (); /* message parametre incorrect */ ++corps; } else *chaine++ = c; if (c == '\n') { *chaine++ = ''; dansif = recurmacro(ligne, dansif); chaine = ligne; } } } /* definition d'une macro */ defmacro(tchampp) struct stligne *tchampp; { struct stligne tchamp; char *p, c; char copie[120], ligne[120]; strcpy (entc->nom = salloc(strlen(tchampp->etiquette) + 1), tchampp->etiquette); entc->corps = memp; /* memoriser le corps de la macro */ while( fgets(ligne, sizeof ligne, stdin) ) { decompligne(ligne, &tchamp, copie); if ( strcmp ( tchamp.codop, "ENDM" ) == 0 ) break; p = ligne; while( c = *p++ ) { putmacro (c); } } entc++; } /* allocation dynamique de la memoire */ char *salloc (N) { char *p; p = memp; if ( (memp += N) <= mem + MAXMEM) return (p); nonmem (); } /* message de debordement memoire */ nonmem () { fprintf (stderr, " plus d'espace memoire disponible \n"); exit (1); } /* programme principal */ recurmacro(chaine,dansif) char *chaine; { struct stligne tchamp; char copie[120]; struct descripm *macp; if (*chaine =='*') { if (!dansif) fputs(chaine, stdout); return(dansif); } decompligne(chaine, &tchamp, copie); if (strcmp(tchamp.codop, "ENDC") == 0) return(0); if (strcmp(tchamp.codop, "IFEQ")==0 || strcmp(tchamp.codop, "IFNE")==0) return ( ifeqne(equal(tchamp.codop, "IFEQ"), tchamp.paramv[1]) ); if (strcmp(tchamp.codop, "IFC")==0 || strcmp(tchamp.codop, "IFNC")==0 ) return (equal(tchamp.paramv[1], tchamp.paramv[2]) != equal(tchamp.codop, "IFC") ); if (dansif) return(dansif); if ( (macp = ismacro (&tchamp)) != NULL) expandmacro (macp, &tchamp); else if (strcmp (tchamp.codop, "MACRO") == 0) defmacro (&tchamp); else fputs (chaine, stdout); return(dansif); } /* programme principal */ main () { int dansif; char ligne[120]; dansif = 0; while (fgets(ligne, sizeof ligne, stdin) != NULL) dansif = recurmacro(ligne, dansif); } equal(a,b) { return (!strcmp(a,b)); } ifeqne(iseqne, string) { return( iseqne==0 ); } /* variables globales */ # define MAXPAR 10 # include # define strend(s) ( (s) + strlen(s) ) /* massive kludjj for kludjy motorola & jerome */ #define hexdigit(c) ( (c>='0' && c<='9') || c=='F') struct stligne { char *etiquette; char *codop; char *comment; int nparam; char *paramv [MAXPAR]; }; /* special directives */ int xop(), dcop(), dsop(), equop(), multop(), sectop(); int condop(), errop(), arg1op(), dcbop(), bclrop(); struct descripm { char *nom; int (*func)(); } pmac[] = { "xref", xop, "xdef", xop, "dc.b", dcop, "dc.w", dcop, "dc.l", dcop, "ds.b", dsop, "ds.w", dsop, "ds.l", dsop, "equ", equop, "set", equop, "movem", multop, "movem.l", multop, "movem.w", multop, "section", sectop, "idnt", NULL, "list", NULL, "nolist", NULL, "nol", NULL, "opt", NULL, "format", NULL, "page", NULL, "org", errop, "org.l", errop, "rorg", errop, "mexit", errop, "spc", NULL, "noobj", NULL, "fail", errop, "nopage", NULL, "ttl", NULL, "end", NULL, "ifeq", errop, "ifne", errop, "rts", arg1op, "nop", arg1op, "dcb.b", dcbop, "dcb.w", dcbop, "dcb.l", dcbop, "bclr.b", bclrop, "bclr.l", bclrop, "bset.b", bclrop, "bset.l", bclrop, "btst.b", bclrop, "btst.l", bclrop, NULL }; struct stligne tchamp ; char ligne [120], copie [120]; char *ptc, *pts; int lnno; char *readln(), *champ(); struct descripm *isspcl(); /* programme principal */ main () { int i; struct descripm *macp; while( readln() ) { if(*ligne == '*') { /* whole line is a comment */ printf("|%s", ligne+1); continue; } if ( (macp = isspcl ()) != NULL) { if (macp->func) (*macp->func)(); else { /* null pseudo op -- echo as comment */ printf("|%s", ligne); continue; } } else { label(); if (*tchamp.codop) outop(tchamp.codop); printargs(); } if(*tchamp.comment!='\n') printf("\t\t|\t%s", tchamp.comment); else printf("\n"); } } /* lit une ligne et la decompose en champs */ char *readln () { register i, brac; register char *pit, c; /* lit une ligne d'un fichier */ if (fgets (ligne, sizeof ligne, stdin) == NULL) return (NULL); lnno++; if (ligne[0]=='*') return (ligne); ptc = ligne; pts = copie; tchamp.etiquette = champ (); tchamp.codop = champ (); pit = champ (); tchamp.comment = ptc; tchamp.nparam = *pit != ''; for (i = 0; i < MAXPAR; i++) /* remplacer les , par des */ { tchamp.paramv[i] = pit; brac = 0; while (c = *pit) { switch (c) { case ',': if (!brac) goto out; break; case '(': brac++; break; case ')': brac--; break; } pit++; } out: if (c == ',') { *pit++ = ''; tchamp.nparam++; } } return (ligne); } char *champ () { char c, *ptd = pts; while (*ptc != '\n') { if (*ptc == '\t' || *ptc == ' ') { /* remplacer les blancs et les tabulation par des 0 */ *pts++ = ''; while (*++ptc == ' ' || *ptc == '\t') ; return (ptd); } if ((c = *ptc++) == '\'') { *pts++ = '\''; while ( (c = getquote()) ) *pts++ = c; *pts++ = '\''; } else { if (c=='$' && hexdigit(*ptc) ) { *pts++ = '0'; *pts++ = 'x'; } else { if (c>='A' && c<='Z') c += 'a' - 'A'; *pts++ = c; } } } *pts++ = ''; return (ptd); } getquote() { char c; if ((c = *ptc++) == '\'') { if( *ptc=='\'' ) { ptc++; return (c); } return(NULL); } if (!c || c=='\n') { werr("newline or EOF in string"); return(NULL); } return(c); } /* fonction recherchant le nom d'une macro dans le descrip. des macros */ struct descripm *isspcl () { struct descripm *macp; for (macp = pmac; macp->nom; macp++) { if (strcmp (tchamp.codop, macp->nom) == 0) return (macp); } return (NULL); } char *defops[] = { "add", "addx", "and", "asl", "asr", "cmp", "clr", "ext", "lsl", "lsl", "move", "neg", "negx", "not", "or", "rol", "ror", "roxl", "roxr", "sub", "subq", "tst", "addq", "subx", /* forgot these ones !!! */ NULL }; outop(op) register char *op; { register char **opp; putchar('\t'); opp = defops; while( *opp ) if (strcmp(*(opp++), op)==0) { printf("%sw", strcmp(op, "move") ?op : "mov"); return; } if (strncmp(op, "move", 4) == 0) printf("mov"); else begop(op); restop(op); } substarg(arg) register char *arg; { /* first off, find the index register */ register char *areg, *dreg, *offs, *offe, disp, incrdecr; char *end; register brac; end = strend(arg) - 1; areg = dreg = 0; disp = 0; if (*end == '+') { incrdecr = '+'; end--; } if (*arg == '-' ) incrdecr = '-'; if( end>=arg && *end == ')') { brac = 1; while( brac && --end >= arg ) { if (*end == '(') brac--; else if (*end == ')') brac++; } offs = arg; offe = end; areg = end + 1; if (areg[2] == ',') { dreg = areg + 3; if (areg[2+3] == '.') disp = areg[3+3]; } } else { outoff(arg, strend(arg)); return; } printf("%c%c@", areg[0], areg[1]); if (incrdecr) putchar(incrdecr); else if (offs!=offe || dreg) { putchar('('); if (offs==offe) putchar('0'); else outoff(offs, offe); if( dreg ) printf(",%c%c", dreg[0], dreg[1]); if( disp ) printf(":%c", disp); putchar(')'); } } outoff(offs, offe) register char *offs, *offe; { register char c; register inquote = 0; int state; state = 0; while (offs='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' & c<='9') ) return(1); return(0); } struct reg { char *rname; int rno; } regnames[] = { "d0", 0, "d1", 1, "d2", 2, "d3", 3, "d4", 4, "d5", 5, "d6", 6, "d7", 7, "a0", 8, "a1", 9, "a2", 10, "a3", 11, "a4", 12, "a5", 13, "a6", 14, "sp", 15, "a7", 15, "pc", -1, NULL } ; isreg(s) { register struct reg *rp; for (rp=regnames; rp->rname; rp++) if (strncmp(rp->rname, s, 2) == 0) return(rp->rno); return(-1); } sectop() { label(); if( !strcmp(tchamp.paramv[0], "10") || !strcmp(tchamp.paramv[0],"9")) printf("\t.text"); else if (strcmp(tchamp.paramv[0], "15") == 0) printf("\t.data"); else if ( strcmp(tchamp.paramv[0], "14") == 0) printf("\t.bss"); else werr("bad argument to section directive"); } equop() { printf("%s = ", tchamp.etiquette); substarg(tchamp.paramv[0]); } xop() { printf("\t.globl"); printargs(); } dcop() { register i; label(); for (i=0; i0) printf("\t%s\t%s\n", w, init); } strop(s) register char *s; { register char *start, *end, c; align(tchamp.codop[3]); printf("\t.ascii\t"); start = s + 1; end = strend(start) - 1; putchar('"'); while (start < end) { if ( (c = *start++) == '"' || c == '\' ) putchar('\'); putchar(c); } printf("\"\n"); align(tchamp.codop[3]); } dsop() { label(); align(tchamp.codop[3]); printf(". = "); switch(tchamp.codop[3]) { default: case 'b': printf("1"); break; case 'w': printf("2"); break; case 'l': printf("4"); break; } printf("*"); substarg(tchamp.paramv[0]); printf(" + ."); } multop() { unsigned short mask, flipbits(), multbits(); register regs, mem; label(); if (strcmp(tchamp.codop, "movem.l")==0) printf("\tmoveml"); else printf("\tmovemw"); printf("\t"); regs = isreg(tchamp.paramv[1]) >= 0; mem = !regs; mask = multbits(tchamp.paramv[regs]); if (tchamp.paramv[mem][0] == '-' ) mask = flipbits(mask); if (regs==0) printf("#0x%04x", mask); else substarg(tchamp.paramv[0]); putchar(','); if (regs==0) substarg(tchamp.paramv[1]); else printf("#0x%04x", mask); } unsigned short multbits(s) register char *s; { register unsigned short mask; register rn, r2n; int temp; mask = 0; while ((rn = isreg(s)) >= 0) { if (s[2]=='-') { if ((r2n = isreg(s+=3)) < 0) break; if (r2n>= 1) if (word&test) val |= rev; return (val); } errop() { char s[80]; sprintf(s, "unknown directive %s", tchamp.codop); werr(s); } werr(s) char *s; { fprintf(stderr, "line %d: %s\n", lnno, s); } begop(op) register char *op; { register char c; while ( (c = *op++) && c!='.' ) putchar(c); } restop(op) register char *op; { register char c; while ( (c = *op++) && c!='.' ) ; if (c) while( c = *op++ ) putchar(c); } align(c) { if (c != 'b') printf("\t.even\n"); } printargs() { register i; if (tchamp.nparam==0) return; putchar('\t'); for(i=0; i