1*49438Sbostic /*-
2*49438Sbostic * Copyright (c) 1984, 1986 The Regents of the University of California.
3*49438Sbostic * All rights reserved.
4*49438Sbostic *
5*49438Sbostic * %sccs.include.redist.c%
623350Smckusick */
716962Smckusick
816962Smckusick #ifndef lint
923350Smckusick char copyright[] =
10*49438Sbostic "@(#) Copyright (c) 1984, 1986 The Regents of the University of California.\n\
1123350Smckusick All rights reserved.\n";
12*49438Sbostic #endif /* not lint */
1316962Smckusick
1423350Smckusick #ifndef lint
15*49438Sbostic static char sccsid[] = "@(#)main.c 7.2 (Berkeley) 05/08/91";
16*49438Sbostic #endif /* not lint */
1723350Smckusick
1816962Smckusick #include <stdio.h>
1916962Smckusick #include <ctype.h>
2016963Smckusick #include "inline.h"
2116962Smckusick
2216975Smckusick /*
2316975Smckusick * These are the pattern tables to be loaded
2416975Smckusick */
2527462Skarels struct pats *vax_inittables[] = {
2616975Smckusick language_ptab,
2716975Smckusick libc_ptab,
2827462Skarels vax_libc_ptab,
2916975Smckusick machine_ptab,
3027462Skarels vax_ptab,
3116975Smckusick 0
3216975Smckusick };
3316975Smckusick
3427462Skarels struct pats *vaxsubset_inittables[] = {
3527462Skarels language_ptab,
3627462Skarels libc_ptab,
3727462Skarels vaxsubset_libc_ptab,
3827462Skarels machine_ptab,
3927462Skarels vaxsubset_ptab,
4027462Skarels 0
4127462Skarels };
4227462Skarels
4316980Smckusick /*
4416980Smckusick * Statistics collection
4516980Smckusick */
4616980Smckusick struct stats {
4716980Smckusick int attempted; /* number of expansion attempts */
4816980Smckusick int finished; /* expansions done before end of basic block */
4916980Smckusick int lostmodified; /* mergers inhibited by intervening mod */
5016980Smckusick int savedpush; /* successful push/pop merger */
5116980Smckusick } stats;
5224395Smckusick
5324395Smckusick extern char *strcpy();
5424395Smckusick
5524395Smckusick char *whoami;
5624395Smckusick int lineno = 0;
5716980Smckusick int dflag;
5816980Smckusick
main(argc,argv)5916962Smckusick main(argc, argv)
6016962Smckusick int argc;
6116962Smckusick char *argv[];
6216962Smckusick {
6316962Smckusick register char *cp, *lp;
6416962Smckusick register char *bufp;
6516978Smckusick register struct pats *pp, **php;
6616978Smckusick struct pats **tablep;
6716978Smckusick register struct inststoptbl *itp, **ithp;
6816962Smckusick int size;
6916962Smckusick extern char *index();
7027462Skarels int subset = 0;
7116962Smckusick
7224395Smckusick whoami = argv[0];
7327899Skarels argc--;
7427899Skarels argv++;
7527899Skarels while (argc > 0 && argv[0][0] == '-') {
7627899Skarels switch(argv[0][1]) {
7727462Skarels
7827462Skarels case 's':
7927462Skarels subset++;
8027462Skarels break;
8127462Skarels
8227462Skarels case 'd':
8327462Skarels dflag++;
8427462Skarels break;
8527462Skarels
8627462Skarels default:
8727462Skarels break;
8827462Skarels }
8927462Skarels argc--, argv++;
9027462Skarels }
9127899Skarels if (argc > 0)
9227899Skarels freopen(argv[0], "r", stdin);
9316962Smckusick if (argc > 1)
9427899Skarels freopen(argv[1], "w", stdout);
9516962Smckusick /*
9616978Smckusick * Set up the hash table for the patterns.
9716962Smckusick */
9827462Skarels if (subset)
9927462Skarels tablep = vaxsubset_inittables;
10027462Skarels else
10127462Skarels tablep = vax_inittables;
10227462Skarels for ( ; *tablep; tablep++) {
10316975Smckusick for (pp = *tablep; pp->name[0] != '\0'; pp++) {
10416978Smckusick php = &patshdr[hash(pp->name, &size)];
10516975Smckusick pp->size = size;
10616978Smckusick pp->next = *php;
10716978Smckusick *php = pp;
10816975Smckusick }
10916962Smckusick }
11016962Smckusick /*
11116978Smckusick * Set up the hash table for the instruction stop table.
11216978Smckusick */
11316978Smckusick for (itp = inststoptable; itp->name[0] != '\0'; itp++) {
11416978Smckusick ithp = &inststoptblhdr[hash(itp->name, &size)];
11516978Smckusick itp->size = size;
11616978Smckusick itp->next = *ithp;
11716978Smckusick *ithp = itp;
11816978Smckusick }
11916978Smckusick /*
12016962Smckusick * check each line and replace as appropriate
12116962Smckusick */
12216962Smckusick buftail = bufhead = 0;
12316962Smckusick bufp = line[0];
12416962Smckusick while (fgets(bufp, MAXLINELEN, stdin)) {
12524395Smckusick lineno++;
12616962Smckusick lp = index(bufp, LABELCHAR);
12716962Smckusick if (lp != NULL) {
12818448Smckusick for (cp = bufp; cp < lp; cp++)
12918448Smckusick if (!isalnum(*cp))
13018448Smckusick break;
13118448Smckusick if (cp == lp) {
13218448Smckusick bufp = newline();
13318448Smckusick if (*++lp == '\n') {
13418448Smckusick emptyqueue();
13518448Smckusick continue;
13618448Smckusick }
13724395Smckusick (void) strcpy(bufp, lp);
13818448Smckusick *lp++ = '\n';
13918448Smckusick *lp = '\0';
14016962Smckusick emptyqueue();
14116962Smckusick }
14216962Smckusick }
14316962Smckusick for (cp = bufp; isspace(*cp); cp++)
14416962Smckusick /* void */;
14516962Smckusick if ((cp = doreplaceon(cp)) == 0) {
14616962Smckusick bufp = newline();
14716962Smckusick continue;
14816962Smckusick }
14916978Smckusick for (pp = patshdr[hash(cp, &size)]; pp; pp = pp->next) {
15016962Smckusick if (pp->size == size && bcmp(pp->name, cp, size) == 0) {
15124395Smckusick if (argcounterr(pp->args, countargs(bufp), pp->name)) {
15224395Smckusick pp = NULL;
15324395Smckusick break;
15424395Smckusick }
15516962Smckusick expand(pp->replace);
15616962Smckusick bufp = line[bufhead];
15716962Smckusick break;
15816962Smckusick }
15916962Smckusick }
16016962Smckusick if (!pp) {
16116962Smckusick emptyqueue();
16216962Smckusick fputs(bufp, stdout);
16316962Smckusick }
16416962Smckusick }
16516962Smckusick emptyqueue();
16616980Smckusick if (dflag)
16724395Smckusick fprintf(stderr, "%s: %s %d, %s %d, %s %d, %s %d\n",
16824395Smckusick whoami,
16916980Smckusick "attempts", stats.attempted,
17016980Smckusick "finished", stats.finished,
17116980Smckusick "inhibited", stats.lostmodified,
17216980Smckusick "merged", stats.savedpush);
17316962Smckusick exit(0);
17416962Smckusick }
17516962Smckusick
17616962Smckusick /*
17716962Smckusick * Integrate an expansion into the assembly stream
17816962Smckusick */
expand(replace)17916962Smckusick expand(replace)
18016962Smckusick char *replace;
18116962Smckusick {
18216962Smckusick register int curptr;
18316962Smckusick char *nextreplace, *argv[MAXARGS];
18417202Smckusick int argc, argreg, foundarg, mod = 0, args = 0;
18516962Smckusick char parsebuf[BUFSIZ];
18616962Smckusick
18716980Smckusick stats.attempted++;
18816980Smckusick for (curptr = bufhead; ; ) {
18916962Smckusick nextreplace = copyline(replace, line[bufhead]);
19016962Smckusick argc = parseline(line[bufhead], argv, parsebuf);
19116962Smckusick argreg = nextarg(argc, argv);
19216962Smckusick if (argreg == -1)
19316962Smckusick break;
19417202Smckusick args++;
19516978Smckusick for (foundarg = 0; curptr != buftail; ) {
19616978Smckusick curptr = PRED(curptr);
19716962Smckusick argc = parseline(line[curptr], argv, parsebuf);
19816978Smckusick if (isendofblock(argc, argv))
19916962Smckusick break;
20016978Smckusick if (foundarg = ispusharg(argc, argv))
20116978Smckusick break;
20216962Smckusick mod |= 1 << modifies(argc, argv);
20316962Smckusick }
20416978Smckusick if (!foundarg)
20516962Smckusick break;
20616962Smckusick replace = nextreplace;
20716962Smckusick if (mod & (1 << argreg)) {
20816980Smckusick stats.lostmodified++;
20916978Smckusick if (curptr == buftail) {
21016978Smckusick (void)newline();
21116978Smckusick break;
21216978Smckusick }
21316962Smckusick (void)newline();
21416962Smckusick } else {
21516980Smckusick stats.savedpush++;
21616962Smckusick rewrite(line[curptr], argc, argv, argreg);
21716962Smckusick mod |= 1 << argreg;
21816962Smckusick }
21916962Smckusick }
22016980Smckusick if (argreg == -1)
22116980Smckusick stats.finished++;
22216962Smckusick emptyqueue();
22316962Smckusick fputs(replace, stdout);
22417202Smckusick cleanup(args);
22516962Smckusick }
22616962Smckusick
22716962Smckusick /*
22816962Smckusick * Parse a line of assembly language into opcode and arguments.
22916962Smckusick */
parseline(linep,argv,linebuf)23016962Smckusick parseline(linep, argv, linebuf)
23116962Smckusick char *linep;
23216962Smckusick char *argv[];
23316962Smckusick char *linebuf;
23416962Smckusick {
23516962Smckusick register char *bufp = linebuf, *cp = linep;
23616962Smckusick register int argc = 0;
23716962Smckusick
23816962Smckusick for (;;) {
23916962Smckusick /*
24016962Smckusick * skip over white space
24116962Smckusick */
24216962Smckusick while (isspace(*cp))
24316962Smckusick cp++;
24416962Smckusick if (*cp == '\0')
24516962Smckusick return (argc);
24616962Smckusick /*
24716962Smckusick * copy argument
24816962Smckusick */
24916962Smckusick if (argc == MAXARGS - 1) {
25016962Smckusick fprintf(stderr, "instruction too long->%s", linep);
25116962Smckusick return (argc);
25216962Smckusick }
25316962Smckusick argv[argc++] = bufp;
25416978Smckusick while (!isspace(*cp) && *cp != ARGSEPCHAR && *cp != COMMENTCHAR)
25516962Smckusick *bufp++ = *cp++;
25616962Smckusick *bufp++ = '\0';
25716962Smckusick if (*cp == COMMENTCHAR)
25816962Smckusick return (argc);
25916978Smckusick if (*cp == ARGSEPCHAR)
26016962Smckusick cp++;
26116962Smckusick }
26216962Smckusick }
26316962Smckusick
26416962Smckusick /*
26516978Smckusick * Check for instructions that end a basic block.
26616978Smckusick */
isendofblock(argc,argv)26716978Smckusick isendofblock(argc, argv)
26816978Smckusick int argc;
26916978Smckusick char *argv[];
27016978Smckusick {
27116978Smckusick register struct inststoptbl *itp;
27216978Smckusick int size;
27316978Smckusick
27416978Smckusick if (argc == 0)
27516978Smckusick return (0);
27616978Smckusick for (itp = inststoptblhdr[hash(argv[0], &size)]; itp; itp = itp->next)
27716978Smckusick if (itp->size == size && bcmp(argv[0], itp->name, size) == 0)
27816978Smckusick return (1);
27916978Smckusick return (0);
28016978Smckusick }
28116978Smckusick
28216978Smckusick /*
28316962Smckusick * Copy a newline terminated string.
28416962Smckusick * Return pointer to character following last character copied.
28516962Smckusick */
28616962Smckusick char *
copyline(from,to)28716962Smckusick copyline(from, to)
28816962Smckusick register char *from, *to;
28916962Smckusick {
29016962Smckusick
29116962Smckusick while (*from != '\n')
29216962Smckusick *to++ = *from++;
29316962Smckusick *to++ = *from++;
29416962Smckusick *to = '\0';
29516962Smckusick return (from);
29616962Smckusick }
29716962Smckusick
29816962Smckusick /*
29924395Smckusick * Check for a disparity between the number of arguments a function
30024395Smckusick * is called with and the number which we expect to see.
30124395Smckusick * If the error is unrecoverable, return 1, otherwise 0.
30224395Smckusick */
argcounterr(args,callargs,name)30324395Smckusick argcounterr(args, callargs, name)
30424395Smckusick int args, callargs;
30524395Smckusick char *name;
30624395Smckusick {
30724395Smckusick register char *cp;
30824395Smckusick char namebuf[MAXLINELEN];
30924395Smckusick
31024395Smckusick if (args == callargs)
31124395Smckusick return (0);
31224395Smckusick cp = strcpy(namebuf, name);
31324395Smckusick while (*cp != '\0' && *cp != '\n')
31424395Smckusick ++cp;
31524395Smckusick if (*cp == '\n')
31624395Smckusick *cp = '\0';
31724395Smckusick if (callargs >= 0) {
31824395Smckusick fprintf(stderr,
31924395Smckusick "%s: error: arg count mismatch, %d != %d for '%s' at line %d\n",
32024395Smckusick whoami, callargs, args, namebuf, lineno);
32124395Smckusick return (1);
32224395Smckusick }
32324395Smckusick fprintf(stderr,
32424395Smckusick "%s: warning: can't verify arg count for '%s' at line %d\n",
32524395Smckusick whoami, namebuf, lineno);
32624395Smckusick return (0);
32724395Smckusick }
32824395Smckusick
32924395Smckusick /*
33016962Smckusick * open space for next line in the queue
33116962Smckusick */
33216962Smckusick char *
newline()33316962Smckusick newline()
33416962Smckusick {
33516962Smckusick bufhead = SUCC(bufhead);
33616962Smckusick if (bufhead == buftail) {
33716962Smckusick fputs(line[buftail], stdout);
33816962Smckusick buftail = SUCC(buftail);
33916962Smckusick }
34016962Smckusick return (line[bufhead]);
34116962Smckusick }
34216962Smckusick
34316962Smckusick /*
34416962Smckusick * empty the queue by printing out all its lines.
34516962Smckusick */
emptyqueue()34616962Smckusick emptyqueue()
34716962Smckusick {
34816962Smckusick while (buftail != bufhead) {
34916962Smckusick fputs(line[buftail], stdout);
35016962Smckusick buftail = SUCC(buftail);
35116962Smckusick }
35216962Smckusick }
35316962Smckusick
35416962Smckusick /*
35516962Smckusick * Compute the hash of a string.
35616962Smckusick * Return the hash and the size of the item hashed
35716962Smckusick */
hash(cp,size)35816962Smckusick hash(cp, size)
35916962Smckusick char *cp;
36016962Smckusick int *size;
36116962Smckusick {
36216962Smckusick register char *cp1 = cp;
36316978Smckusick register int hash = 0;
36416962Smckusick
36516962Smckusick while (*cp1 && *cp1 != '\n')
36616962Smckusick hash += (int)*cp1++;
36716962Smckusick *size = cp1 - cp + 1;
36816962Smckusick hash &= HSHSIZ - 1;
36916978Smckusick return (hash);
37016962Smckusick }
371