koreth@panarthea.ebay.sun.com (Steven Grimm) (10/25/89)
Submitted-by: ncar.ucar.edu!dunike!onecom!wldrdg!hans (Johann Ruegg) Posting-number: Volume 2, Issue 93 Archive-name: sozobon1.2/part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 9)." # Contents: hcc/MAIN.C hcc/MD.C hcc/NODES.H top/FUNC.C top/INST.C # top/PEEP1.C # Wrapped by koreth@panarthea on Tue Oct 24 18:40:44 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'hcc/MAIN.C' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hcc/MAIN.C'\" else echo shar: Extracting \"'hcc/MAIN.C'\" \(8368 characters\) sed "s/^X//" >'hcc/MAIN.C' <<'END_OF_FILE' X/* Copyright (c) 1988,1989 by Sozobon, Limited. Author: Johann Ruegg X * X * Permission is granted to anyone to use this software for any purpose X * on any computer system, and to redistribute it freely, with the X * following restrictions: X * 1) No charge may be made other than reasonable charges for reproduction. X * 2) Modified versions must be clearly marked as such. X * 3) The authors are not responsible for any harmful consequences X * of using this software, even if they result from defects in it. X * X * main.c X * X * Main routine, error handling, keyword lookup. X */ X X#include <stdio.h> X#include "param.h" X#include "nodes.h" X#include "tok.h" X Xint lineno; Xint nmerrors; Xint oflags[26]; Xint xflags[26]; Xint pflag = 0; /* enable profiling */ Xstatic int anydebug; X#define debug oflags['z'-'a'] X XFILE *input; XFILE *output; X#if CC68 XFILE *fopenb(); X#define fopen fopenb X#endif Xchar *inname; X X#if NEEDBUF Xchar my_ibuf[BUFSIZ]; X#endif X X#ifdef MINIX X#define strchr index X#endif X XNODEP cur; X X#define MAXPREDEF 20 X Xstruct def { X char *dname, *dval; X} defines[MAXPREDEF] = { X {"MC68000"}, X {"mc68000"}, X {"SOZOBON"}, X#ifdef FOR_AMIGA X {"AMIGA"}, X {"AMIGADOS"}, X#else X {"ATARI_ST"}, X#ifdef MINIX X {"MINIX"}, X#else X {"TOS"}, X#endif X#endif X}; Xstatic int npred = 4; X X#ifdef MINIX Xchar tmpdir[128] = "."; /* where the output goes */ X#endif X Xmain(argc, argv) Xchar **argv; X{ X char *p, *getenv(); X int shownames; X int i; X X if (sizeof(NODE) & 3) { X printf("sizeof NODE not mult of 4\n"); X exit(1); X } X X /* X * Parse the INCLUDE environment variable, if present. X */ X if ((p = getenv("INCLUDE")) != NULL) X doincl(p); X X shownames = 0; X#ifndef FOR_AMIGA X if (isatty(0)) { X#ifndef MINIX X write(1, "\33v", 2); X#endif X setbuf(stdout, NULL); X } X#endif X/* put author here */ X while (argc-- > 1) { X argv++; X if (argv[0][0] == '-') X doopt(&argv[0][1]); X#if CC68 X else if (argv[0][0] == '+') { X upstr(&argv[0][1]); X doopt(&argv[0][1]); X } X#endif X else { X if (argc > 1 || shownames) { X shownames++; X printf("%s:\n", argv[0]); X } X if (input != NULL) X fclose(input); X input = fopen(argv[0], ROPEN); X if (input == NULL) { X printf("Cant open %s\n", argv[0]); X exit(1); X } X#if NEEDBUF X setbuf(input, my_ibuf); X#endif X inname = argv[0]; X dofile(); X } X } X if (input == NULL) { X input = stdin; X output = stdout; X inname = "<STDIN>"; X dofile(); X } X exit(0); X} X Xadddef(s) Xchar *s; X{ X char *as, *strchr(); X X if (npred >= MAXPREDEF) { X warn("too many -D 's"); X return; X } X if ((as = strchr(s,'=')) != NULL) X *as++ = 0; X else X as = NULL; X defines[npred].dname = s; X defines[npred].dval = as; X npred++; X} X Xsubdef(s) Xchar *s; X{ X int i; X X for (i=0; i<npred; i++) X if (strcmp(s, defines[i].dname) == 0) X goto found; X return; Xfound: X while (i < npred) { X defines[i] = defines[i+1]; X i++; X } X npred--; X} X Xdodefs() X{ X int i; X struct def *p; X X /* X * Define the "built-in" macros X */ X p = defines; X for (i=0; i < npred; i++,p++) X optdef(p->dname, p->dval ? p->dval : "1"); X} X Xdoincl(s) Xchar *s; X{ X char *malloc(), *strcpy(); X char buf[256]; X char dir[128]; X register char *p; X char c; X X strcpy(buf, s); X X /* X * Convert ',' and ';' to nulls X */ X for (p=buf; *p != '\0' ;p++) X if (*p == ',' || *p == ';') X *p = '\0'; X p[1] = '\0'; /* double null terminated */ X X /* X * Grab each directory, make sure it ends with a slash X * and add it to the directory list. X */ X for (p=buf; *p != '\0' ;p++) { X strcpy(dir, p); X c = dir[strlen(dir)-1]; X#ifndef FOR_AMIGA X#ifdef MINIX X if (c != '/') X strcat(dir, "/"); X#else X if (c != '\\') X strcat(dir, "\\"); X#endif X#else X if (c != '/' && c != ':') X strcat(dir, "/"); X#endif X X optincl( strcpy(malloc((unsigned) (strlen(dir) + 1)), dir) ); X X while (*p != '\0') X p++; X } X} X Xdofile() X{ X extern int nodesmade, nodesavail; X char *scopy(); X extern NODEP deflist[], symtab[], tagtab; X extern NODEP strsave; X extern int level; X int i; X X out_start(inname); X inname = scopy(inname); X lineno = 1; X nmerrors = 0; X dodefs(); X advnode(); X X level = 0; X program(); X dumpstrs(strsave); X#ifdef OUT_AZ X xrefs(); X#endif X X out_end(); X if (cur && cur->e_token == EOFTOK) X freenode(cur); X sfree(inname); X for (i=0; i<NHASH; i++) { X if (debug>1 && deflist[i]) { X printf("defines[%d]", i); X printlist(deflist[i]); X } X freenode(deflist[i]); X deflist[i] = NULL; X if (debug && symtab[i]) { X printf("gsyms[%d]", i); X printlist(symtab[i]); X } X freenode(symtab[i]); X symtab[i] = NULL; X } X if (debug) { X printf("structs"); X printlist(tagtab); X } X freenode(tagtab); X tagtab = NULL; X freenode(strsave); X strsave = NULL; X if (nmerrors) { X printf("%d errors\n", nmerrors); X exit(1); X } X if (nodesmade != nodesavail) { X printf("lost %d nodes!!!\n", nodesmade-nodesavail); X exit(1); X } X/* X printf("Space = %ldK\n", ((long)nodesavail*sizeof(NODE))/1024); X*/ X} X Xstatic char Version[] = X"hcc: version 1.20 Copyright (c) 1988,1989 by Sozobon, Limited."; X Xdoopt(s) Xchar *s; X{ X register char c; X X while ((c = *s++)) { X#ifdef DEBUG X if (c >= 'a' && c <='z') { X oflags[c-'a']++; X anydebug++; X } else X#endif X if (c >= 'A' && c <= 'Z') { X switch (c) { X case 'D': X adddef(s); X return; X case 'U': X subdef(s); X return; X case 'I': X doincl(s); X return; X case 'P': X pflag = 1; X continue; X case 'V': X printf("%s\n", Version); X continue; X#ifdef MINIX X case 'T': X strcpy(tmpdir, s); X if (tmpdir[strlen(tmpdir)-1] == '/') X tmpdir[strlen(tmpdir)-1] = '\0'; X return; X#endif X } X#ifdef DEBUG X xflags[c-'A']++; X anydebug++; X#endif X } X } X} X Xerrors(s,t) Xchar *s, *t; X{ X optnl(); X printf("error in %s on line %d: %s %s\n", inname, lineno, s,t); X nmerrors++; X} X Xerrorn(s,np) Xchar *s; XNODE *np; X{ X optnl(); X printf("error in %s on line %d: %s ", inname, lineno, s); X put_nnm(np); X putchar('\n'); X nmerrors++; X} X Xerror(s) Xchar *s; X{ X optnl(); X printf("error in %s on line %d: %s\n", inname, lineno, s); X nmerrors++; X} X Xwarns(s,t) Xchar *s, *t; X{ X optnl(); X printf("warning in %s on line %d: %s %s\n", inname, lineno, s,t); X} X Xwarnn(s,np) Xchar *s; XNODE *np; X{ X optnl(); X printf("warning in %s on line %d: %s ", inname, lineno, s); X put_nnm(np); X putchar('\n'); X} X Xwarn(s) Xchar *s; X{ X optnl(); X printf("warning in %s on line %d: %s\n", inname, lineno, s); X} X Xfatals(s,t) Xchar *s, *t; X{ X optnl(); X printf("fatal error in %s on line %d: %s %s\n", inname, lineno, s,t); X exit(1); X} X Xfataln(s,np) Xchar *s; XNODE *np; X{ X optnl(); X printf("fatal error in %s on line %d: %s ", inname, lineno, s); X put_nnm(np); X putchar('\n'); X exit(1); X} X Xfatal(s) Xchar *s; X{ X optnl(); X printf("fatal error in %s on line %d: %s\n", inname, lineno, s); X exit(1); X} X Xstatic Xoptnl() X{ X if (anydebug) X putchar('\n'); X} X Xstruct kwtbl { X char *name; X int kwval; X int kflags; X} kwtab[] = { X /* must be sorted */ X {"asm", K_ASM}, X {"auto", K_AUTO}, X {"break", K_BREAK}, X {"case", K_CASE}, X {"char", K_CHAR}, X {"continue", K_CONTINUE}, X {"default", K_DEFAULT}, X {"do", K_DO}, X {"double", K_DOUBLE}, X {"else", K_ELSE}, X {"enum", K_ENUM}, X {"extern", K_EXTERN}, X {"float", K_FLOAT}, X {"for", K_FOR}, X {"goto", K_GOTO}, X {"if", K_IF}, X {"int", K_INT}, X {"long", K_LONG}, X {"register", K_REGISTER}, X {"return", K_RETURN}, X {"short", K_SHORT}, X {"sizeof", K_SIZEOF}, X {"static", K_STATIC}, X {"struct", K_STRUCT}, X {"switch", K_SWITCH}, X {"typedef", K_TYPEDEF}, X {"union", K_UNION}, X {"unsigned", K_UNSIGNED}, X {"void", K_VOID}, X {"while", K_WHILE}, X X {0,0} X}; X X#define FIRST_C 'a' X#define LAST_C 'z' Xstruct kwtbl *kwstart[LAST_C-FIRST_C+1]; X Xkw_init() X{ X register struct kwtbl *p; X register c; X X for (p=kwtab; p->name; p++) { X c = p->name[0]; X if (kwstart[c-FIRST_C] == 0) X kwstart[c-FIRST_C] = p; X } X} X Xkw_tok(tp) XNODE *tp; X{ X register struct kwtbl *kp; X register char *nm; X register i; X static first = 0; X X nm = tp->n_name; X if (first == 0) { X kw_init(); X first = 1; X } X i = nm[0]; X if (i < FIRST_C || i > LAST_C) X return; X kp = kwstart[i-FIRST_C]; X if (kp) X for (; kp->name; kp++) { X i = strcmp(nm, kp->name); X if (i == 0) { X tp->e_token = kp->kwval; X tp->e_flags = kp->kflags; X return; X } else if (i < 0) X return; X } X} X X#if CC68 X/* fix args since stupid lib makes all lower case */ Xupstr(s) Xchar *s; X{ X while (*s) { X if (*s >= 'a' && *s <= 'z') X *s += 'A'-'a'; X s++; X } X} Xdownstr(s) Xchar *s; X{ X while (*s) { X if (*s >= 'A' && *s <= 'Z') X *s -= 'A'-'a'; X s++; X } X} X#endif END_OF_FILE if test 8368 -ne `wc -c <'hcc/MAIN.C'`; then echo shar: \"'hcc/MAIN.C'\" unpacked with wrong size! fi # end of 'hcc/MAIN.C' fi if test -f 'hcc/MD.C' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hcc/MD.C'\" else echo shar: Extracting \"'hcc/MD.C'\" \(7524 characters\) sed "s/^X//" >'hcc/MD.C' <<'END_OF_FILE' X/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg X * X * Permission is granted to anyone to use this software for any purpose X * on any computer system, and to redistribute it freely, with the X * following restrictions: X * 1) No charge may be made other than reasonable charges for reproduction. X * 2) Modified versions must be clearly marked as such. X * 3) The authors are not responsible for any harmful consequences X * of using this software, even if they result from defects in it. X * X * md.c X * X * Machine dependant parts of first pass (parse) X * Also type checking subroutines. X */ X X#include <stdio.h> X#include "param.h" X#include "tok.h" X#include "nodes.h" X#include "cookie.h" X XNODEP bas_type(); X Xint adjtab[] = { X K_INT, /* none */ X K_SHORT, /* short */ X K_LONG, /* long */ X 0, /* short long */ X K_UNSIGNED, /* unsigned */ X K_UNSIGNED, /* unsigned short */ X T_ULONG, /* unsigned long */ X 0, /* unsigned short long */ X}; X Xadj_type(old, adj) X{ X int rv; X X switch (old) { X case K_CHAR: X if (adj & SAW_UNS) X return T_UCHAR; X break; X case K_INT: X rv = adjtab[adj]; X if (rv == 0) { X error("bad type spec"); X return K_INT; X } X return rv; X case K_FLOAT: X if (adj & SAW_LONG) X return K_DOUBLE; X break; X } X return old; X} X X/* given ICON value, and flags SEE_L,SEE_U X determine final type */ Xicon_ty(tp) XNODE *tp; X{ X int flags; X long val; X int islong, isuns; X X flags = tp->e_flags; X val = tp->e_ival; X X islong = (flags & SEE_L); X isuns = (flags & SEE_U); X X if (islong && isuns) X return T_ULONG; X if (islong || islongv(val)) X return K_LONG; X if (isuns) X return K_UNSIGNED; X return isintv((int)val) ? K_INT : K_CHAR; X} X Xisintv(i) X{ X if (i > 0x7f || i < -0x80) X return 1; X return 0; X} X Xislongv(l) Xlong l; X{ X#ifndef NOLONGS X#define HIBITS 0xffff0000L X X if ((l & HIBITS) == 0) /* upper 16 bits zero */ X return 0; X X if ((l & HIBITS) == HIBITS) { /* upper bits all on */ X if (l & 0x8000L) X return 0; /* upper bits aren't significant */ X else X return 1; X } X return 1; X#else X return 0; X#endif X} X Xmkint(l) Xlong l; X{ X return l; X} X Xlc_reg(rp, xp) Xint *rp; XNODE *xp; X{ X switch (xp->n_tptr->t_token) { X case STAR: X return al_areg(rp,xp); X case K_CHAR: X case T_UCHAR: X case T_ULONG: X case K_INT: X case K_UNSIGNED: X case K_LONG: X return al_dreg(rp,xp); X default: X return 0; X } X} X Xal_areg(rp,xp) Xint *rp; XNODEP xp; X{ X register rmask, n; X X rmask = *rp; X for (n=ARV_START; n<=ARV_END; n++) X if ((rmask & (1<<n)) == 0) { X xp->e_rno = n; X *rp |= (1<<n); X return 1; X } X return 0; X} X Xal_dreg(rp,xp) Xint *rp; XNODEP xp; X{ X register rmask, n; X X rmask = *rp; X for (n=DRV_START; n<=DRV_END; n++) X if ((rmask & (1<<n)) == 0) { X xp->e_rno = n; X *rp |= (1<<n); X return 1; X } X return 0; X} X Xlong Xarg_size(sz,np) Xlong sz; XNODEP np; X{ X np->e_offs = 0; X X switch (np->n_tptr->t_token) { X case '[': X printf("GAK! array arg "); X return SIZE_P; X case K_CHAR: X case T_UCHAR: X np->e_offs = SIZE_I - SIZE_C; X return SIZE_I; X#if SIZE_I != SIZE_S X case K_SHORT: X np->e_offs = SIZE_I - SIZE_S; X return SIZE_I; X#endif X default: X if (sz & 1) X sz++; X return sz; X } X} X Xmustlval(np) XNODEP np; X{ X switch (np->e_token) { X case ID: X case STAR: X case '.': X break; X default: X errorn("not lvalue", np); X return 1; X } X return 0; X} X Xmustty(np, flags) XNODEP np; X{ X switch (np->n_tptr->t_token) { X case STAR: X if (flags & R_POINTER) X return 0; X error("pointer not allowed"); X return 1; X case K_STRUCT: X case K_UNION: X if (flags & R_STRUCT) X return 0; X error("struct/union not allowed"); X return 1; X case K_CHAR: X case K_SHORT: X case K_INT: X case K_UNSIGNED: X case K_LONG: X case T_UCHAR: X case T_ULONG: X if (flags & R_INTEGRAL) X return 0; X error("integral not allowed"); X return 1; X case K_FLOAT: X case K_DOUBLE: X if (flags & R_FLOATING) X return 0; X error("floating not allowed"); X return 1; X default: X error("bad type"); X return 1; X } X return 0; X} X XNODEP Xfuncty(np) XNODEP np; X{ X int lt; X X lt = np->n_tptr->t_token; X if (lt != K_VOID) X mustty(np, R_ASSN); X switch (lt) { X case STAR: X case K_STRUCT: X case K_UNION: X return np->n_tptr; X } X lt = widen(lt); X return bas_type(lt); X} X XNODEP Xnormalty(lp, rp) XNODEP lp, rp; X{ X /* already checked types are R_ARITH */ X /* rp may be NULL */ X int lt, rt, rett; X X lt = lp->n_tptr->t_token; X if (rp) X rt = rp->n_tptr->t_token; X else X rt = K_INT; X rett = maxt(widen(lt), widen(rt)); X return bas_type(rett); X} X Xasn_chk(ltp, rp) XNODEP ltp, rp; X{ X X switch (ltp->t_token) { X case K_STRUCT: X case K_UNION: X if (same_type(ltp, rp->n_tptr) == 0) X error("bad struct assign"); X return; X case STAR: X if (mayzero(rp)) X return; X if (mustty(rp, R_POINTER)) X return; X if (same_type(ltp->n_tptr, rp->n_tptr->n_tptr) X == 0) X warn("pointer types mismatch"); X return; X default: X if (mustty(rp, R_ARITH)) X return; X } X} X Xchkcmp(np) XNODEP np; X{ X /* already checked types are R_SCALAR */ X int lt, rt; X NODEP lp = np->n_left, rp = np->n_right; X X lt = lp->n_tptr->t_token; X lt = (lt == STAR); X rt = rp->n_tptr->t_token; X rt = (rt == STAR); X if (lt && rt) { /* ptr cmp ptr */ X if (same_type(lp->n_tptr, rp->n_tptr) == 0) { X warn("cmp of diff ptrs"); X } X } else if (lt) { /* ptr cmp intg */ X mustzero(rp); X } else if (rt) { /* intg +-[ ptr */ X mustzero(lp); X } /* else both ARITH */ X} X XNODEP Xcolonty(np) XNODEP np; X{ X /* already checked types are R_SCALAR */ X int lt, rt; X NODEP lp = np->n_left, rp = np->n_right; X X lt = lp->n_tptr->t_token; X lt = (lt == STAR); X rt = rp->n_tptr->t_token; X rt = (rt == STAR); X if (lt && rt) { /* ptr : ptr */ X warn(": diff ptrs"); X return lp->n_tptr; X } else if (lt) { /* ptr : intg */ X mustzero(rp); X return lp->n_tptr; X } else if (rt) { X mustzero(lp); X return rp->n_tptr; X } else X return normalty(lp, rp); X} X XNODEP Xaddty(np) XNODEP np; X{ X /* already checked types are R_SCALAR */ X /* op is '+' or '-' or '+=' or '-=' or '[' */ X int oop = np->e_token; X int op; X int lt, rt; X NODEP lp = np->n_left, rp = np->n_right; X X op = oop; X if (isassign(op)) X op -= ASSIGN 0; X lt = lp->n_tptr->t_token; X lt = (lt == STAR); X rt = rp->n_tptr->t_token; X rt = (rt == STAR); X if (lt && rt) { /* ptr - ptr */ X if (oop != '-' || same_type(lp->n_tptr, rp->n_tptr) == 0) { X error("bad +/-"); X return lp->n_tptr; X } X np->e_token = PTRDIFF; X np->e_offs = lp->n_tptr->n_tptr->t_size; X return bas_type(K_INT); X } else if (lt) { /* ptr +-[ intg */ Xpandi: X mustty(rp, R_INTEGRAL); X np->e_offs = lp->n_tptr->n_tptr->t_size; X if (op == '+') X np->e_token += PTRADD-'+'; X else if (op == '-') X np->e_token += PTRSUB-'-'; X return lp->n_tptr; X } else if (rt) { /* intg +-[ ptr */ X if (isassign(oop) || op == '-') { X error("illegal int op ptr"); X return bas_type(K_INT); X } X /* switch sides so intg is on right */ X np->n_left = rp; X np->n_right = lp; X lp = rp; X rp = np->n_right; X goto pandi; X } else { /* intg +- intg */ X return normalty(lp, rp); X } X} X Xmustzero(np) XNODEP np; X{ X if (np->e_token == ICON && np->e_ival == 0) { X return; X } X error("bad ':' combination"); X} X Xmayzero(np) XNODEP np; X{ X if (np->e_token == ICON && np->e_ival == 0) { X return 1; X } X return 0; X} X Xwiden(ty) X{ X switch (ty) { X case K_CHAR: X case T_UCHAR: X return K_INT; X case K_SHORT: X return K_INT; X case K_FLOAT: X return K_DOUBLE; X default: X return ty; X } X} X Xint pri_t[] = { X 1, 6, /* uchar, ulong */ X 5,2,4,3,0, /* long, short, uns, int, char */ X 7,8,9 /* float, double, void */ X}; X Xmaxt(t1, t2) X{ X extern nmerrors; X X if (nmerrors) X return K_INT; X if (pri_t[t1-FIRST_BAS] > pri_t[t2-FIRST_BAS]) X return t1; X return t2; X} END_OF_FILE if test 7524 -ne `wc -c <'hcc/MD.C'`; then echo shar: \"'hcc/MD.C'\" unpacked with wrong size! fi # end of 'hcc/MD.C' fi if test -f 'hcc/NODES.H' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hcc/NODES.H'\" else echo shar: Extracting \"'hcc/NODES.H'\" \(4451 characters\) sed "s/^X//" >'hcc/NODES.H' <<'END_OF_FILE' X/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg X * X * Permission is granted to anyone to use this software for any purpose X * on any computer system, and to redistribute it freely, with the X * following restrictions: X * 1) No charge may be made other than reasonable charges for reproduction. X * 2) Modified versions must be clearly marked as such. X * 3) The authors are not responsible for any harmful consequences X * of using this software, even if they result from defects in it. X * X * nodes.h X */ X X/* X * stuff common to all nodes X */ X#define COMMON int cflags; \ X int fill; \ X union node *left; \ X union node *right; \ X union node *tptr; \ X union node *nm_ext; \ X char cname[NMSIZE] X X#define n_flags e.cflags X#define n_left e.left X#define n_next e.left X#define n_right e.right X#define n_tptr e.tptr X#define n_nmx e.nm_ext X#define n_name e.cname X X/* X * expression (and symbol table) node X */ Xstruct enode { X COMMON; X int token; /* must be same place as tnode */ X int eflags; X char etype; /* type of node */ X char sc; X char eprec; X char rno; X union { X long vival; X long voffs; X double vfval; X } vu; X#ifndef NOFIELDS X unsigned fldw:6, fldof:6; /* use fields just so X we know fields work */ X#else X char fldw, fldof; /* use if cant do fields */ X#endif X}; X X#define e_token e.token X#define e_flags e.eflags X#define e_prec e.eprec X#define e_rno e.rno X#define e_type e.etype X#define e_ival e.vu.vival X#define e_offs e.vu.voffs X#define e_fval e.vu.vfval X#define e_sc e.sc X#define e_fldw e.fldw X#define e_fldo e.fldof X X/* for e_flags values, see tok.h */ X X/* values for e_type */ X X#define E_LEAF 0 /* no descendants */ X#define E_UNARY 1 /* left node is expr, no right node */ X#define E_BIN 2 /* left and right are expr */ X#define E_SPEC 3 /* special '(', '[', '.', '->', ... */ X X/* X * code generation node X */ Xstruct gnode { X COMMON; X int token; X int eflags; X char etype; X char sc; X/* all of above fields must match first fields in enode! */ X X char needs; /* registers needed */ X char grno; /* register used in ret value */ X char basety; /* type FLOAT, UNS, INT or AGREG */ X char basesz; /* size 1,2,4 or 3 -> see bsize */ X char gr1, gr2; X char *betwc; /* code for between L and R */ X long goffs; /* offsets for OREG, ONAME */ X union gu { X long bsize; /* AGREG size or misc. */ X struct { X#ifndef NOFIELDS X#ifdef AZ_HOST X unsigned gfldw:6, gfldo:6; /* BUG! */ X#else X int gfldw:6, gfldo:6; /* field info */ X#endif X#else X char gfldw, gfldo; /* use if no fields */ X#endif X } gfl; X } gu; X}; X X#define g_token g.token X#define g_flags g.eflags X#define g_type g.etype X#define g_sc g.sc X#define g_needs g.needs X#define g_rno g.grno X#define g_offs g.goffs X#define g_betw g.betwc X#define g_ty g.basety X#define g_sz g.basesz X#define g_code g.tptr X#define g_bsize g.gu.bsize X#define g_fldw g.gu.gfl.gfldw X#define g_fldo g.gu.gfl.gfldo X#define g_r1 g.gr1 X#define g_r2 g.gr2 X X/* types of operands -- ordered in cast strength order */ X#define ET_S 1 /* signed integer */ X#define ET_U 2 /* unsigned integer */ X#define ET_F 3 /* float or double */ X#define ET_A 4 /* aggregate */ X X/* X * type list node X */ Xstruct tnode { X COMMON; X int token; /* must be same place as enode */ X int tflags; X char aln; /* alignment needed */ X long tsize; X}; X X#define t_token t.token X#define t_flags t.tflags X#define t_size t.tsize X#define t_aln t.aln X X/* X * name extension node X */ Xstruct nmext { X COMMON; X char nmx[NMXSIZE-NMSIZE]; /* name extension (with name)*/ X}; X X#define x_nm x.nmx X X/* X * block info node X */ Xstruct bnode { X COMMON; X union node *syms; X union node *tags; X int regs; /* reg alloc mask */ X long lsize; /* size of locals */ X int tmsize; /* max tmps used for 1 expr */ X}; X X#define b_syms b.syms X#define b_tags b.tags X#define b_regs b.regs X#define b_size b.lsize X#define b_tsize b.tmsize X X/* X * node to hold case for switch generation X */ Xstruct cnode { X COMMON; X int c_value; /* value for case */ X int c_label; /* case label or label label */ X int c_def; /* label defined */ X}; X X#define c_defined c.c_def X#define c_casev c.c_value X#define c_casel c.c_label X Xunion node { X struct enode e; X struct tnode t; X struct nmext x; X struct bnode b; X struct cnode c; X struct gnode g; X}; X Xtypedef union node NODE; Xtypedef NODE *NODEP; X X/* defines for n_flags */ X X#define N_BRKPR 1 /* break printnode recursion */ X#define N_COPYT 2 /* tptr is a copy */ X#define N_ISFREE 4 /* node is on free list (error check) */ X XNODEP allocnode(); END_OF_FILE if test 4451 -ne `wc -c <'hcc/NODES.H'`; then echo shar: \"'hcc/NODES.H'\" unpacked with wrong size! fi # end of 'hcc/NODES.H' fi if test -f 'top/FUNC.C' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'top/FUNC.C'\" else echo shar: Extracting \"'top/FUNC.C'\" \(4582 characters\) sed "s/^X//" >'top/FUNC.C' <<'END_OF_FILE' X/* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews X * X * Permission is granted to anyone to use this software for any purpose X * on any computer system, and to redistribute it freely, with the X * following restrictions: X * 1) No charge may be made other than reasonable charges for reproduction. X * 2) Modified versions must be clearly marked as such. X * 3) The authors are not responsible for any harmful consequences X * of using this software, even if they result from defects in it. X */ X#include "top.h" X XBLOCK *fhead; /* head of the current function */ X X/* X * dofunc() - process one function X * X * Returns FALSE on end of file X */ Xbool Xdofunc() X{ X BLOCK *getfunc(); X X clrvar(); X X#ifdef DEBUG X if (debug) X fprintf(stderr, "dofunc() - calling getfunc()\n"); X#endif X if ((fhead = getfunc()) == NULL) X return FALSE; X X /* X * Process the function we just read X */ X bopt(fhead); /* perform branch optimization */ X X if (do_regs) X setreg(fhead); /* try to assign locals to registers */ X X if (do_peep) { X rhealth(fhead, TRUE); /* live/dead register analysis */ X peep(fhead); /* peephole optimizations */ X } X X /* X * Now dump out the modified tree X */ X#ifdef DEBUG X if (debug) X fprintf(stderr, "dofunc() - calling putfunc()\n"); X#endif X putfunc(fhead); X X freesym(); /* free the symbol table */ X X return TRUE; X} X Xstatic bool saw_eof = FALSE; X X/* X * getfunc() - get a function and return a pointer to its starting block X * X * Returns NULL on end of file. X */ XBLOCK * Xgetfunc() X{ X register BLOCK *head; /* starting block for this function */ X register BLOCK *cb; /* the block we're currently reading */ X register BLOCK *ob; /* the last block we read */ X X if (saw_eof) X return NULL; X X head = NULL; X X /* X * Starting a global function X */ X if (strcmp(t_op, ".globl") == 0) { X /* X * Enter the symbol and mark it global. X */ X head = mksym(t_arg); X head->flags |= B_GLOBAL; X X readline(); X } X X ob = NULL; X X for (;;) { X if (ob == NULL) { X if (t_lab[0] != '_') { X fprintf(stderr, "top: expected function label\n"); X exit(1); X } X if (head == NULL) X head = mksym(t_lab); X X } else if (t_lab[0] == '\0') { X fprintf(stderr, "top: expected block label\n"); X exit(1); X } X X if ((cb = getsym(t_lab)) == NULL) X cb = mksym(t_lab); X X /* X * The last block falls through to this one. X */ X if (ob != NULL) { X ob->chain = cb; X ob->next = cb; X ob->bfall = cb; X } X X t_lab[0] = '\0'; X X /* X * Now read lines until we hit a new block or another X * function. X */ X for (;;) { X /* X * If we see a global, we're done with the function X */ X if (strcmp(t_op, ".globl") == 0) X return head; X /* X * If we see a function label, we're done too. X */ X if (t_lab[0] == '_') X return head; X /* X * If we see any other label, we're done with the block. X */ X if (t_lab[0]) X break; X X addinst(cb, t_op, t_arg); X X /* X * If we're at EOF, note that we've hit the end of X * file, but return the function we just read. X */ X if (!readline()) { X saw_eof = TRUE; X return head; X } X } X ob = cb; X } X} X X/* X * putfunc(sb) - print out the function starting at block 'sb' X * X * The 'next' pointers determine the order in which things are placed X * in the file. Branch instructions have been removed so they need to X * be replaced here on output. Conditional branches are generated if X * indicated (by non-null 'bcond'). Unconditional branches are generated X * at the end of a block if it's "fall through" block isn't going to X * be the next thing in the file. X */ Xputfunc(sb) Xregister BLOCK *sb; X{ X register BLOCK *cb; X register INST *ci; X X fprintf(ofp, "\t.text\n"); X X for (cb = sb; cb != NULL ;cb = cb->next) { X if (cb->flags & B_GLOBAL) X fprintf(ofp, "\t.globl\t%s\n", cb->name); X X if (*cb->name == '_') X fprintf(ofp, "%s:\n", cb->name); X X else if (cb->flags & B_LABEL) X fprintf(ofp, "%s:\n", cb->name); X#ifdef DEBUG X if (debug) { X fprintf(ofp, "*\n"); X fprintf(ofp, "* %s, ref:%04x set:%04x\n", X cb->name, cb->rref, cb->rset); X fprintf(ofp, "*\n"); X } X#endif X X for (ci = cb->first; ci != NULL ;ci = ci->next) X putinst(ci); X /* X * If there's a conditional branch, put out the X * appropriate instruction for it. X */ X if (cb->bcond != NULL && cb->bcode >= 0) X fprintf(ofp, "\t%s\t%s\n", X opnames[cb->bcode], cb->bcond->name); X /* X * If there's a "fall through" label, and the destination X * block doesn't come next, put out a branch. X */ X if (cb->bfall != NULL && cb->bfall != cb->next) { X s_badd++; X fprintf(ofp, "\tbra\t%s\n", cb->bfall->name); X } X } X} END_OF_FILE if test 4582 -ne `wc -c <'top/FUNC.C'`; then echo shar: \"'top/FUNC.C'\" unpacked with wrong size! fi # end of 'top/FUNC.C' fi if test -f 'top/INST.C' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'top/INST.C'\" else echo shar: Extracting \"'top/INST.C'\" \(7882 characters\) sed "s/^X//" >'top/INST.C' <<'END_OF_FILE' X/* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews X * X * Permission is granted to anyone to use this software for any purpose X * on any computer system, and to redistribute it freely, with the X * following restrictions: X * 1) No charge may be made other than reasonable charges for reproduction. X * 2) Modified versions must be clearly marked as such. X * 3) The authors are not responsible for any harmful consequences X * of using this software, even if they result from defects in it. X */ X X/* X * Routines dealing with the parsing and output of instructions. X */ X X#include "top.h" X Xstatic void getarg(); Xstatic int isreg(); X X/* X * addinst(bp, op, args) - add an instruction to block 'bp' X */ Xvoid Xaddinst(bp, op, args) Xregister BLOCK *bp; Xchar *op, *args; X{ X register INST *ni; X register int i; X register char *s; X char *arg2 = ""; X X if (*op == '\0') /* no instruction there */ X return; X X ni = (INST *) alloc(sizeof(INST)); X X ni->flags = 0; X ni->opcode = -1; X ni->next = NULL; X ni->prev = NULL; X ni->live = 0; X ni->rref = ni->rset = 0; X X ni->src.areg = ni->dst.areg = 0; X ni->src.ireg = ni->dst.ireg = 0; X ni->src.disp = ni->dst.disp = 0; X ni->src.amode = ni->dst.amode = NONE; X X /* X * Link into the block appropriately X */ X if (bp->first == NULL) { X bp->first = bp->last = ni; X } else { X bp->last->next = ni; X ni->prev = bp->last; X X bp->last = ni; X } X X for (s = op; *s ;s++) { X /* X * Pseudo-ops start with a period, so the length X * specifier can't be the first character. X */ X if (*s == '.' && s != op) { /* length specifier */ X *s++ = '\0'; X switch (*s) { X case 'b': X ni->flags |= LENB; X break; X case 'w': X ni->flags |= LENW; X break; X case 'l': X ni->flags |= LENL; X break; X default: X fprintf(stderr, "Bad length spec '%c'\n", *s); X exit(1); X } X } X } X X for (i=0; opnames[i] ;i++) { X if (strcmp(op, opnames[i]) == 0) { X ni->opcode = i; X break; X } X } X X if (ni->opcode < 0) { X fprintf(stderr, "Unknown op '%s'\n", op); X exit(1); X } X X /* X * Look for the split between the first and second operands. X */ X for (s = args; *s ;s++) { X /* X * skip chars in parens, since an operand split can't X * occur within. X */ X if (*s == '(') { X while (*s != ')') X s++; X } X if (*s == ',') { X *s++ = '\0'; X arg2 = s; X break; X } X } X X getarg(&ni->src, args); X getarg(&ni->dst, arg2); X} X X/* X * delinst(bp, ip) - delete instruction 'ip' in block 'bp' X */ Xvoid Xdelinst(bp, ip) XBLOCK *bp; Xregister INST *ip; X{ X register INST *pi, *ni; /* previous and next instructions */ X X pi = ip->prev; X ni = ip->next; X X if (pi != NULL) X pi->next = ni; X else X bp->first = ni; X X if (ni != NULL) X ni->prev = pi; X else X bp->last = pi; X X /* X * Free space used by the instruction. X */ X freeop(&ip->src); X freeop(&ip->dst); X free(ip); X X s_idel++; X} X X/* X * getarg(op, s) - parse string 's' into the operand structure 'op' X * X * Hack alert!! The following code parses the operands only to the X * extent needed by the optimizer. We're primarily interested in X * details about addressing modes used, not in any expressions that X * might be present. This code is highly tuned to the output of the X * compiler. X */ Xstatic void Xgetarg(op, s) Xregister struct opnd *op; Xregister char *s; X{ X extern long atol(); X register int reg; X register char *p; X X if (*s == '\0') { X op->amode = NONE; X return; X } X X if (*s == '#') { /* immediate data */ X op->amode = IMM; X s += 1; X if (isdigit(s[0]) || s[0] == '-') X op->disp = atol(s); X else { X op->amode |= SYMB; X op->astr = strsave(s); X } X return; X } else if ((reg = isreg(s)) >= 0) { /* reg. direct */ X op->amode = REG; X op->areg = reg; X } else if (s[0] == '(' || (s[0] == '-' && s[1] == '(')) { X op->amode = REGI; X if (s[0] == '-') { X op->amode |= DEC; X s++; X } X s++; /* skip the left paren */ X if ((op->areg = isreg(s)) < 0) { X fprintf(stderr, "bad reg. '%s'\n", s); X exit(1); X } X s += 3; /* skip the register and right paren */ X X if (s[0] == '+') X op->amode |= INC; X } else if (!isdigit(s[0]) && (s[0] != '-')) { X op->amode = ABS; X op->astr = strsave(s); X } else { X for (p=s; isdigit(*p) || *p == '-' ;p++) X ; X if (*p != '(') { X /* X * Must have been absolute, but with an X * address instead of a symbol. X */ X op->amode = ABS; X op->astr = strsave(s); X return; X } X *p++ = '\0'; X op->disp = atol(s); X s = p; X if (s[0] == 'p' && s[1] == 'c') { /* PC relative */ X if (s[2] == ')') { X op->amode = PCD; X return; X } X op->amode = PCDX; X op->ireg = isreg(s+3); X if (s[6] == 'l') X op->amode |= XLONG; X } else if ((reg = isreg(s)) >= 0) { X op->areg = reg; X if (s[2] == ')') { X op->amode = REGID; X return; X } X op->amode = REGIDX; X op->ireg = isreg(s+3); X if (s[6] == 'l') X op->amode |= XLONG; X } else { X fprintf(stderr, "bad reg. '%s' after disp\n", s); X exit(1); X } X } X} X X/* X * characters that can terminate a register name X */ X#define isterm(c) ((c) == '\0' || (c) == ')' || (c) == ',' || (c) == '.') X Xstatic int Xisreg(s) Xregister char *s; X{ X if (s[0] == 'd' && isdigit(s[1]) && isterm(s[2])) X return D0 + (s[1] - '0'); X if (s[0] == 'a' && isdigit(s[1]) && isterm(s[2])) X return A0 + (s[1] - '0'); X if (s[0] == 's' && s[1] == 'p' && isterm(s[2])) X return SP; X X return -1; X} X X X/* X * Routines for printing out instructions X */ X Xstatic char *rstr(); Xstatic void putop(); X Xvoid Xputinst(ip) Xregister INST *ip; X{ X char c; X X fprintf(ofp, "\t%s", opnames[ip->opcode]); X X switch (ip->flags) { X case LENB: X c = 'b'; X break; X case LENW: X c = 'w'; X break; X case LENL: X c = 'l'; X break; X default: X c = '\0'; X break; X } X if (c) X fprintf(ofp, ".%c", c); X X if (ip->src.amode != NONE) { X fprintf(ofp, "\t"); X putop(&ip->src); X } X X if (ip->dst.amode != NONE) { X fprintf(ofp, ","); X putop(&ip->dst); X } X#ifdef DEBUG X if (debug) X fprintf(ofp, "\t\t* ref(%04x), set(%04x), live(%04x)", X reg_ref(ip), reg_set(ip), ip->live); X#endif X fprintf(ofp, "\n"); X} X Xstatic void Xputop(op) Xregister struct opnd *op; X{ X switch (op->amode & MMASK) { X case NONE: X break; X case REG: X fprintf(ofp, "%s", rstr(op->areg)); X break; X case IMM: X if (op->amode & SYMB) X fprintf(ofp, "#%s", op->astr); X else X fprintf(ofp, "#%ld", op->disp); X break; X case ABS: X fprintf(ofp, "%s", op->astr); X break; X case REGI: X if (op->amode & DEC) X fprintf(ofp, "-"); X fprintf(ofp, "(%s)", rstr(op->areg)); X if (op->amode & INC) X fprintf(ofp, "+"); X break; X case REGID: X fprintf(ofp, "%ld(%s)", op->disp, rstr(op->areg)); X break; X case REGIDX: X fprintf(ofp, "%ld(%s,", op->disp, rstr(op->areg)); X fprintf(ofp, "%s.%c)", rstr(op->ireg), X (op->amode & XLONG) ? 'l' : 'w'); X break; X case PCD: X fprintf(ofp, "%ld(pc)", op->disp); X break; X case PCDX: X fprintf(ofp, "%ld(pc,%s.%c)", op->disp, rstr(op->ireg), X (op->amode & XLONG) ? 'l' : 'w'); X break; X default: X fprintf(stderr, "bad addr. mode in putop: %d\n", op->amode); X exit(1); X } X} X Xstatic char * Xrstr(r) Xregister char r; X{ X static char buf[3]; X X if (r == SP) { X buf[0] = 's'; X buf[1] = 'p'; X } else if (r >= A0 && r <= A6) { X buf[0] = 'a'; X buf[1] = '0' + (r - A0); X } else { X buf[0] = 'd'; X buf[1] = '0' + (r - D0); X } X buf[2] = '\0'; X X return buf; X} X X/* X * opeq(op1, op2) - test equality of the two instruction operands X */ Xbool Xopeq(op1, op2) Xregister struct opnd *op1, *op2; X{ X if (op1->amode != op2->amode || op1->areg != op2->areg || X op1->ireg != op2->ireg) X return FALSE; X X /* X * Depending on the addressing mode, we either need to X * compare the "astr" strings, or the displacements. X */ X if ((op1->amode == ABS) || (op1->amode == (IMM|SYMB))) { X /* compare strings */ X if (op1->astr == NULL) X return (op2->astr == NULL); X else { X if (op2->astr == NULL) X return FALSE; X X return (strcmp(op1->astr, op2->astr) == 0); X } X } else { X /* compare displacements */ X return (op1->disp == op2->disp); X } X} END_OF_FILE if test 7882 -ne `wc -c <'top/INST.C'`; then echo shar: \"'top/INST.C'\" unpacked with wrong size! fi # end of 'top/INST.C' fi if test -f 'top/PEEP1.C' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'top/PEEP1.C'\" else echo shar: Extracting \"'top/PEEP1.C'\" \(5178 characters\) sed "s/^X//" >'top/PEEP1.C' <<'END_OF_FILE' X/* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews X * X * Permission is granted to anyone to use this software for any purpose X * on any computer system, and to redistribute it freely, with the X * following restrictions: X * 1) No charge may be made other than reasonable charges for reproduction. X * 2) Modified versions must be clearly marked as such. X * 3) The authors are not responsible for any harmful consequences X * of using this software, even if they result from defects in it. X */ X X/* X * Single-instruction peephole optimizations and the overall driver routine. X */ X X#include "top.h" X X Xvoid Xpeep(bp) Xregister BLOCK *bp; X{ X bool peep1(), peep2(), peep3(); X extern BLOCK *fhead; X register bool changed; X X peep1(bp); X X /* X * Loop until no more changes are made. After each change, do X * live/dead analysis or the data gets old. In each loop, make X * at most one change. X */ X do { X changed = peep3(bp); X X if (!changed) X changed = peep2(bp); X X if (!changed) X changed = peep1(bp); X X rhealth(fhead, FALSE); X X } while (changed); X} X X/* X * ipeep1(ip) - check for changes to the instruction 'ip' X */ Xstatic bool Xipeep1(bp, ip) Xregister BLOCK *bp; Xregister INST *ip; X{ X /* X * clr.l Dn => moveq.l Dn X */ X if (ip->opcode == CLR && ip->src.amode == REG && X ISD(ip->src.areg) && (ip->flags & LENL)) { X ip->opcode = MOVEQ; X ip->dst = ip->src; /* we'll have two operands now */ X ip->src.amode = IMM; X ip->src.disp = 0; X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * move.* #n,Dn => moveq.l #n,Dn X * X * moveq is always a long operation, but as long as the immediate X * value is appropriate, we don't care what the original length X * was. Clearing upper bytes won't matter. X */ X if (ip->opcode == MOVE && ip->src.amode == IMM && ISD(ip->dst.areg) && X D8OK(ip->src.disp)) { X ip->opcode = MOVEQ; X ip->flags = LENL; X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * add.x #n, X => addq.x #n, X X * X * where 1 <= n <= 8 X */ X if (ip->opcode == ADD && ip->src.amode == IMM && X ip->src.disp >= 1 && ip->src.disp <= 8) { X ip->opcode = ADDQ; X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * sub.x #n, X => subq.x #n, X X * X * where 1 <= n <= 8 X */ X if (ip->opcode == SUB && ip->src.amode == IMM && X ip->src.disp >= 1 && ip->src.disp <= 8) { X ip->opcode = SUBQ; X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * movem.x Reg,-(sp) => move.x Reg,-(sp) X */ X if (ip->opcode == MOVEM && ip->src.amode == REG && X ip->dst.areg == SP && ip->dst.amode == (REGI|DEC)) { X ip->opcode = MOVE; X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * movem.x (sp)+,Reg => move.x (sp)+,Reg X */ X if (ip->opcode == MOVEM && ip->dst.amode == REG && X ip->src.amode == (REGI|INC) && ip->src.areg == SP) { X ip->opcode = MOVE; X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * add[q] #?, Rn X * X * Remove instruction if Rn is dead. This is most often used X * to eliminate the fixup of SP following a function call when X * we're just about to return, since the "unlk" clobbers SP X * anyway. X */ X if ((ip->opcode == ADDQ || ip->opcode == ADD) && ip->src.amode == IMM && X ip->dst.amode == REG) { X X if ((ip->live & RM(ip->dst.areg)) == 0) { X delinst(bp, ip); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * move.x X, X X * X * Delete as long as X isn't INC or DEC X */ X if ((ip->opcode == MOVE) && opeq(&ip->src, &ip->dst) && X ((ip->src.amode & (INC|DEC)) == 0)) { X X delinst(bp, ip); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X /* X * move.x Rm, Rn X * X * Delete if Rn is dead. X */ X if (ip->opcode == MOVE && X ip->src.amode == REG && ip->dst.amode == REG) { X X if ((ip->live & RM(ip->dst.areg)) == 0) { X delinst(bp, ip); X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X X /* X * cmp.x #0, X => tst.x X X * beq/bne beq/bne X * X * Where X is not An X */ X if (bp->last == ip && (bp->bcode == BEQ || bp->bcode == BNE) && X ip->opcode == CMP && X ((ip->dst.amode != REG) || !ISA(ip->dst.areg))) { X X if (ip->src.amode == IMM && ip->src.disp == 0) { X ip->opcode = TST; X ip->src = ip->dst; X ip->dst.amode = NONE; X DBG(printf("%d ", __LINE__)) X return TRUE; X } X } X X /* X * add.x #n, Am => lea n(Am), Am X * X * where 'n' is a valid displacement X */ X if (ip->opcode == ADD && ip->src.amode == IMM && ip->dst.amode == REG && X ISA(ip->dst.areg) && DOK(ip->src.disp)) { X ip->opcode = LEA; X ip->flags = 0; X ip->src.amode = REGID; X ip->src.areg = ip->dst.areg; X DBG(printf("%d ", __LINE__)) X return TRUE; X } X X return FALSE; X} X X/* X * peep1(bp) - peephole optimizations with a window size of 1 X */ Xstatic bool Xpeep1(bp) Xregister BLOCK *bp; X{ X register INST *ip; X register bool changed = FALSE; X register bool bchange; X X DBG(printf("p1: ")) X for (; bp != NULL ;bp = bp->next) { X bchange = FALSE; X for (ip = bp->first; ip != NULL ;ip = ip->next) { X if (ipeep1(bp, ip)) { X s_peep1++; X changed = TRUE; X bchange = TRUE; X } X } X if (bchange) X bprep(bp); X } X DBG(printf("\n"); fflush(stdout)) X return changed; X} END_OF_FILE if test 5178 -ne `wc -c <'top/PEEP1.C'`; then echo shar: \"'top/PEEP1.C'\" unpacked with wrong size! fi # end of 'top/PEEP1.C' fi echo shar: End of archive 2 \(of 9\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 9 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0