diff -c c68III/analyze.c c68III.1/analyze.c
*** c68III/analyze.c	Mon Feb  4 19:58:25 1991
--- c68III.1/analyze.c	Fri Mar  1 10:49:49 1991
***************
*** 437,443 ****
      bsort(&olist);		/* sort the expression list */
      csp = olist;
      while (csp != 0) {
! 	if (desire(csp) < 3 || (noreg_option && desire(csp) < 5000))
  	    csp->reg = -1;
  	else if (csp->duses > (csp->uses / 3) && addreg < 14
  	    /*
--- 437,447 ----
      bsort(&olist);		/* sort the expression list */
      csp = olist;
      while (csp != 0) {
! /*
!  * If reg_option is not true, the 'desire' value must be at least
!  * 5000, which I hope can only be achieved by the 'register' attribute
!  */
! 	if (desire(csp) < 3 || (!reg_option && desire(csp) < 5000))
  	    csp->reg = -1;
  	else if (csp->duses > (csp->uses / 3) && addreg < 14
  	    /*
***************
*** 533,539 ****
      bsort(&olist);		/* sort the expression list */
      csp = olist;
      while (csp != 0) {
! 	if (desire(csp) < 3 || (noreg_option && desire(csp) < 5000))
  	    csp->reg = -1;
  	else if (reg_use_ptr < number_of_regs
  	    /*
--- 537,547 ----
      bsort(&olist);		/* sort the expression list */
      csp = olist;
      while (csp != 0) {
! /*
!  * If reg_option is not true, the 'desire' value must be at least
!  * 5000, which I hope can only be achieved by the 'register' attribute
!  */
! 	if (desire(csp) < 3 || (!reg_option && desire(csp) < 5000))
  	    csp->reg = -1;
  	else if (reg_use_ptr < number_of_regs
  	    /*
***************
*** 541,547 ****
  	     */
  		 && csp->exp->nodetype != en_icon
  	    /*
! 	     * the types which are fine
  	     */
  		 && (csp->exp->etype == bt_pointer ||
                       csp->exp->etype == bt_long    ||
--- 549,556 ----
  	     */
  		 && csp->exp->nodetype != en_icon
  	    /*
! 	     * the types which are fine: one-byte quantities are illegal
!              * in some of the registers, e.g. %edi and %esi
  	     */
  		 && (csp->exp->etype == bt_pointer ||
                       csp->exp->etype == bt_long    ||
***************
*** 724,729 ****
--- 733,740 ----
   */
      struct snode   *block;
  {
+     if (! opt_option)
+         return;
      olist = 0;
      scan(block);		/* collect expressions */
      allocate();			/* allocate registers */
diff -c c68III/c.h c68III.1/c.h
*** c68III/c.h	Mon Feb  4 19:58:22 1991
--- c68III.1/c.h	Fri Mar  1 10:49:46 1991
***************
*** 112,117 ****
--- 112,121 ----
      char           *sname;
      long            size;
      enum e_bt       type;
+ /*
+  * The following four chars may be unsigned -- no harm.
+  * They could be ints without restriction -- this is to save memory
+  */
      char            val_flag;
      char            st_flag;
      char            bit_width;
***************
*** 132,145 ****
      }
                      value;
      enum e_sc       storage_class;
!     char            used;
  };
  
  #define TYP	struct typ
  #define TABLE	struct stab
  
  #define MAX_STRLEN	1500
  #define MAX_ID_LEN	50
  #define REG_LIST	20
  #define AUTO_LIST	100
  
--- 136,151 ----
      }
                      value;
      enum e_sc       storage_class;
!     int             used;
  };
  
  #define TYP	struct typ
  #define TABLE	struct stab
  
+ #define MAX_ERROR_COUNT 200
  #define MAX_STRLEN	1500
  #define MAX_ID_LEN	50
+ #define MAX_PARAMS	100
  #define REG_LIST	20
  #define AUTO_LIST	100
  
diff -c c68III/cglbdec.h c68III.1/cglbdec.h
*** c68III/cglbdec.h	Mon Feb  4 19:58:47 1991
--- c68III.1/cglbdec.h	Fri Mar  1 10:50:10 1991
***************
*** 48,58 ****
  
  extern int      list_option;
  extern int      short_option;
! extern int      noreg_option;
  extern int      trans_option;
- extern int      nopeep_option;
  extern int	warn_option;
  extern int	fpu_option;
  #ifdef ICODE
  extern int      icode_option;
  #endif
--- 48,58 ----
  
  extern int      list_option;
  extern int      short_option;
! extern int      opt_option;
  extern int      trans_option;
  extern int	warn_option;
  extern int	fpu_option;
+ extern int	reg_option;
  #ifdef ICODE
  extern int      icode_option;
  #endif
diff -c c68III/cglbdef.c c68III.1/cglbdef.c
*** c68III/cglbdef.c	Mon Feb  4 19:58:26 1991
--- c68III.1/cglbdef.c	Fri Mar  1 10:49:50 1991
***************
*** 64,73 ****
  int		short_option = 0;
  int		fpu_option   = 1;
  #endif
! int             noreg_option = 0;
  int             trans_option = 0;
- int             nopeep_option = 0;
  int		warn_option = 0;
  #ifdef ICODE
  int             icode_option = 0;
  #endif
--- 64,73 ----
  int		short_option = 0;
  int		fpu_option   = 1;
  #endif
! int             opt_option = 1;
  int             trans_option = 0;
  int		warn_option = 0;
+ int             reg_option = 1;
  #ifdef ICODE
  int             icode_option = 0;
  #endif
diff -c c68III/cmain.c c68III.1/cmain.c
*** c68III/cmain.c	Mon Feb  4 19:58:27 1991
--- c68III.1/cmain.c	Fri Mar  1 10:49:51 1991
***************
*** 118,124 ****
      char           *s;
  {
      int value = 1;
!     ++s;
      if (s[0] == 'n' && s[1] == 'o') {
  	s += 2;
  	value = 0;
--- 118,126 ----
      char           *s;
  {
      int value = 1;
!     s++; /* forget '-' */
!     if (*s == 'Q')
!         s++; /* forget 'Q' */
      if (s[0] == 'n' && s[1] == 'o') {
  	s += 2;
  	value = 0;
***************
*** 132,138 ****
  	return;
      }
      if (!strcmp(s, "reg")) {
! 	noreg_option = ! value;
  	return;
      }
      if (!strcmp(s, "trans")) {
--- 134,140 ----
  	return;
      }
      if (!strcmp(s, "reg")) {
! 	reg_option = value;
  	return;
      }
      if (!strcmp(s, "trans")) {
***************
*** 139,146 ****
  	trans_option = 1;
  	return;
      }
!     if (!strcmp(s, "peep")) {
! 	nopeep_option = ! value;
  	return;
      }
      if (!strcmp(s, "warn")) {
--- 141,148 ----
  	trans_option = 1;
  	return;
      }
!     if (!strcmp(s, "opt")) {
! 	opt_option = ! value;
  	return;
      }
      if (!strcmp(s, "warn")) {
diff -c c68III/decl.c c68III.1/decl.c
*** c68III/decl.c	Mon Feb  4 19:58:28 1991
--- c68III.1/decl.c	Fri Mar  1 10:49:53 1991
***************
*** 39,45 ****
  
  /* variables for function parameter lists */
  static int      nparms;
! static char    *names[30];	/* 30 parameters maximum */
  
  /* variable for bit fields */
  static int      bit_offset;	/* the actual offset */
--- 39,45 ----
  
  /* variables for function parameter lists */
  static int      nparms;
! static char    *names[MAX_PARAMS];
  
  /* variable for bit fields */
  static int      bit_offset;	/* the actual offset */
***************
*** 312,317 ****
--- 312,319 ----
  	    if (nparms != 0)
  		error(ERR_PARMS);
  	    while (lastst == id) {
+                 if (nparms >= MAX_PARAMS)
+ 		    fatal("MAX_PARAMS");
  		names[nparms++] = strsave(lastid);
  		getsym();
  		if (lastst == comma)
***************
*** 351,359 ****
        case bt_struct:
        case bt_union:
  	return AL_STRUCT;
        default:
  	fatal("alignment: illegal type");
- 	return 1;
      }
  }
  
--- 353,362 ----
        case bt_struct:
        case bt_union:
  	return AL_STRUCT;
+       case bt_void:
+         return 1;
        default:
  	fatal("alignment: illegal type");
      }
  }
  
diff -c c68III/expr.c c68III.1/expr.c
*** c68III/expr.c	Mon Feb  4 19:58:30 1991
--- c68III.1/expr.c	Fri Mar  1 10:49:54 1991
***************
*** 243,248 ****
--- 243,250 ----
      ep1 = 0;
      while (lastst != closepa) {
  	tp = exprnc(&ep2);	/* evaluate a parameter */
+         if (tp == 0)
+             return 0;
  #ifdef INTEL_386
              /* trap struct assigns */
              if (tp->type == bt_struct | tp->type == bt_union)
***************
*** 251,267 ****
  	/*
  	 * do the default promotions
  	 */
! 	if (tp != 0)
!             if (tp->type == bt_float)
! 		tp = cast_op(&ep2, tp, &tp_double);
! 	    if (short_option) {
! 		if (tp->type == bt_char || tp->type == bt_uchar)
! 		    tp = cast_op(&ep2, tp, &tp_short);
! 	    } else {
! 		if (tp->type == bt_uchar || tp->type == bt_char ||
! 		    tp->type == bt_short || tp->type == bt_ushort)
! 		    tp = cast_op(&ep2, tp, &tp_long);
! 	    }
  	ep1 = mk_node(en_void, ep2, ep1);
  	if (lastst != comma)
  	    break;
--- 253,268 ----
  	/*
  	 * do the default promotions
  	 */
!         if (tp->type == bt_float)
! 	    tp = cast_op(&ep2, tp, &tp_double);
!         if (short_option) {
!             if (tp->type == bt_char || tp->type == bt_uchar)
! 		    (void) cast_op(&ep2, tp, &tp_short);
! 	} else {
! 	    if (tp->type == bt_uchar || tp->type == bt_char ||
! 	        tp->type == bt_short || tp->type == bt_ushort)
! 		    (void) cast_op(&ep2, tp, &tp_long);
! 	}
  	ep1 = mk_node(en_void, ep2, ep1);
  	if (lastst != comma)
  	    break;
***************
*** 304,309 ****
--- 305,311 ----
   * primary.id
   * primary->id
   * primary( parameter list )
+  * -- or just a semicolon, yields empty expression --
   *
   */
      struct enode  **node;
***************
*** 316,321 ****
--- 318,325 ----
  
        case id:
  	tptr = nameref(&pnode);
+         if (tptr == 0)
+             break;
          /*
           * function names alone are pointers to functions.
           * If followed by '(', the reference is stripped off
***************
*** 330,336 ****
        case iconst:
        case uconst:
        case lconst:
! 	pnode = mk_icon((long) 0);
  	pnode->v.i = ival;
  	if (lastst == uconst) {
  	    tptr = &tp_uint;
--- 334,340 ----
        case iconst:
        case uconst:
        case lconst:
! 	pnode = mk_icon(0l);
  	pnode->v.i = ival;
  	if (lastst == uconst) {
  	    tptr = &tp_uint;
***************
*** 391,405 ****
  	}
  	break;
        default:
! 	return 0;
      }
      for (;;) {
  	switch (lastst) {
  	  case openbr:		/* build a subscript reference */
  	    tp1 = tptr;
! 	    if (tptr->type != bt_pointer)
  		error(ERR_NOPOINTER);
! 	    else
  		tptr = tptr->btp;
  	    getsym();
  	    qnode = mk_icon((long) tptr->size);
--- 395,412 ----
  	}
  	break;
        default:
! 	tptr=0;
!         break;
      }
+     if (tptr == 0)
+         return 0;
      for (;;) {
  	switch (lastst) {
  	  case openbr:		/* build a subscript reference */
  	    tp1 = tptr;
! 	    if (tptr->type != bt_pointer) {
  		error(ERR_NOPOINTER);
! 	    } else
  		tptr = tptr->btp;
  	    getsym();
  	    qnode = mk_icon((long) tptr->size);
***************
*** 548,554 ****
  	    if (tp->type == bt_pointer)
  		ep2 = mk_icon((long) tp->btp->size);
  	    else {
! 		ep2 = mk_icon((long) 1);
  		if (!integral(tp))
  		    error(ERR_INTEGER);
  	    }
--- 555,561 ----
  	    if (tp->type == bt_pointer)
  		ep2 = mk_icon((long) tp->btp->size);
  	    else {
! 		ep2 = mk_icon(1l);
  		if (!integral(tp))
  		    error(ERR_INTEGER);
  	    }
***************
*** 644,653 ****
  	    tp1 = tail;
  	    decl((TABLE *) 0);
  	    decl1();
! 	    if (head != 0)
  		ep1 = mk_icon((long) head->size);
! 	    else
! 		ep1 = mk_icon((long) 1);
  	    head = tp;
  	    tail = tp1;
  	} else {
--- 651,667 ----
  	    tp1 = tail;
  	    decl((TABLE *) 0);
  	    decl1();
! 	    if (head != 0) {
  		ep1 = mk_icon((long) head->size);
!                 /*
!                  * Guard against the size of not-yet-declared struct/unions
!                  */
!                 if (head->size ==  0) {
! 		    do_warning();
!                     fprintf(stderr," value of 'sizeof' is zero\n");
!                 }
! 	    } else
! 		ep1 = mk_icon(1l);
  	    head = tp;
  	    tail = tp1;
  	} else {
***************
*** 662,668 ****
  	    sizeof_flag--;
  	    if (tp == 0) {
  		error(ERR_SYNTAX);
! 		ep1 = mk_icon((long) 1);
  	    } else
  		ep1 = mk_icon((long) tp->size);
  	}
--- 676,682 ----
  	    sizeof_flag--;
  	    if (tp == 0) {
  		error(ERR_SYNTAX);
! 		ep1 = mk_icon(1l);
  	    } else
  		ep1 = mk_icon((long) tp->size);
  	}
***************
*** 829,835 ****
  	switch (tp2->type) {
  	  case bt_char:
  	  case bt_uchar:
! 	    tp2 = cast_op(node2, tp2, &tp_short);
  	  case bt_short:
  	  case bt_long:
  	  case bt_ushort:
--- 843,850 ----
  	switch (tp2->type) {
  	  case bt_char:
  	  case bt_uchar:
! 	    (void) cast_op(node1, tp1, &tp_short);
! 	    return cast_op(node2, tp2, &tp_short);
  	  case bt_short:
  	  case bt_long:
  	  case bt_ushort:
***************
*** 846,856 ****
  	  case bt_uchar:
  	    return cast_op(node2, tp2, tp1);
  	  case bt_ushort:
  	  case bt_short:
  	    if (short_option)
! 		tp2 = cast_op(node2, tp2, &tp_ushort);
! 	    else
! 		tp2 = cast_op(node2, tp2, &tp_long);
  	  case bt_long:
  	  case bt_ulong:
  	  case bt_float:
--- 861,879 ----
  	  case bt_uchar:
  	    return cast_op(node2, tp2, tp1);
  	  case bt_ushort:
+             if (short_option)
+                return cast_op (node1, tp1, &tp_ushort);
+             else {
+                (void) cast_op (node1, tp1, &tp_long);
+                return cast_op (node2, tp2, &tp_long);
+             }
  	  case bt_short:
  	    if (short_option)
! 		return cast_op(node2, tp2, &tp_ushort);
! 	    else {
!                (void) cast_op (node1, tp1, &tp_long);
!                return cast_op (node2, tp2, &tp_long);
!             }
  	  case bt_long:
  	  case bt_ulong:
  	  case bt_float:
***************
*** 865,873 ****
  	  case bt_uchar:
  	  case bt_short:
  	  case bt_ushort:
- 	  case bt_long:
  	    return cast_op(node2, tp2, tp1);
  	  case bt_ulong:
  	  case bt_float:
  	  case bt_double:
  	    return cast_op(node1, tp1, tp2);
--- 888,898 ----
  	  case bt_uchar:
  	  case bt_short:
  	  case bt_ushort:
  	    return cast_op(node2, tp2, tp1);
+           case bt_long:
+             return cast_op(node2, tp2, tp1);
  	  case bt_ulong:
+             return cast_op(node1, tp1, tp2);
  	  case bt_float:
  	  case bt_double:
  	    return cast_op(node1, tp1, tp2);
***************
*** 883,890 ****
  	  case bt_long:
  	  case bt_ulong:
  	  case bt_float:
            case bt_double:
! 	    return cast_op(node2, tp2, tp1);
  	}
  	break;
  	/*
--- 908,916 ----
  	  case bt_long:
  	  case bt_ulong:
  	  case bt_float:
+             return cast_op(node2, tp2, tp1);
            case bt_double:
! 	    return cast_op(node1, tp1, tp2);
  	}
  	break;
  	/*
***************
*** 1285,1304 ****
  	getsym();
  	if ((tp2 = expression(&ep2)) == 0) {
  	    error(ERR_IDEXPECT);
! 	    goto cexit;
  	}
  	needpunc(colon);
  	if ((tp3 = exprnc(&ep3)) == 0) {
  	    error(ERR_IDEXPECT);
! 	    goto cexit;
  	}
  	tp1 = forceft2(&ep2, tp2, &ep3, tp3);
  	ep2 = mk_node(en_void, ep2, ep3);
  	ep1 = mk_node(en_cond, ep1, ep2);
  	ep1->etype = tp1->type;
  	ep1->esize = tp1->size;
      }
! cexit:*node = ep1;
      return tp1;
  }
  
--- 1311,1345 ----
  	getsym();
  	if ((tp2 = expression(&ep2)) == 0) {
  	    error(ERR_IDEXPECT);
! 	    return 0;
  	}
  	needpunc(colon);
  	if ((tp3 = exprnc(&ep3)) == 0) {
  	    error(ERR_IDEXPECT);
! 	    return 0;
  	}
+ /*
+  * If either type is void and the other is not, cast the other one to void.
+  * I dare not doing this in forceft2
+  * Strict ANSI does not allow that only one part of the sentence is void,
+  * that is what gcc -pedantic tells me.
+  * But since such conditionals occur even in GNU Software (look at obstack.h),
+  * I allow such constructs here.
+  */
+         if (tp2->type == bt_void && tp3->type != bt_void)
+             tp3 = cast_op(&ep3, tp3, tp2);
+         else if (tp3->type == bt_void && tp2->type != bt_void)
+             tp2 = cast_op(&ep2, tp2, tp3);
+ 
  	tp1 = forceft2(&ep2, tp2, &ep3, tp3);
+         if (tp1 == 0)
+             return 0;
  	ep2 = mk_node(en_void, ep2, ep3);
  	ep1 = mk_node(en_cond, ep1, ep2);
  	ep1->etype = tp1->type;
  	ep1->esize = tp1->size;
      }
!     *node = ep1;
      return tp1;
  }
  
***************
*** 1322,1334 ****
      ascomm:getsym();
  	    tp2 = asnop(&ep2);
      ascomm2:
! 	    if (tp2 == 0) {
! 		error(ERR_SYNTAX);
! 		break;
! 	    }
  	    if (ep1->nodetype != en_ref && ep1->nodetype != en_fieldref)
  		error(ERR_LVALUE);
  	    tp1 = cast_op(&ep2, tp2, tp1);
  	    ep1 = mk_node(op, ep1, ep2);
  	    ep1->etype = tp1->type;
  	    ep1->esize = tp1->size;
--- 1363,1375 ----
      ascomm:getsym();
  	    tp2 = asnop(&ep2);
      ascomm2:
! 	    if (tp2 == 0)
!                 break;
  	    if (ep1->nodetype != en_ref && ep1->nodetype != en_fieldref)
  		error(ERR_LVALUE);
  	    tp1 = cast_op(&ep2, tp2, tp1);
+             if (tp1 == 0)
+                 break;
  	    ep1 = mk_node(op, ep1, ep2);
  	    ep1->etype = tp1->type;
  	    ep1->esize = tp1->size;
***************
*** 1343,1348 ****
--- 1384,1391 ----
      ascomm3:
  	    getsym();
  	    tp2 = asnop(&ep2);
+             if (tp2 == 0)
+                 break;
  	    if (tp1->type == bt_pointer && integral(tp2)) {
  		(void) cast_op(&ep2, tp2, &tp_long);
  		ep3 = mk_icon((long) tp1->btp->size);
***************
*** 1385,1391 ****
  	    goto asexit;
  	}
      }
! asexit:*node = ep1;
      return tp1;
  }
  
--- 1428,1435 ----
  	    goto asexit;
  	}
      }
! asexit:
!    *node = ep1;
      return tp1;
  }
  
***************
*** 1469,1475 ****
      opt0(ep);			/* to make a constant really a constant */
  
      if ((*ep)->nodetype == en_icon)
! 	if (integral(tp2) || tp2->type == bt_pointer) {
  	    long            j = (*ep)->v.i;
  	    (*ep)->etype = tp2->type;
  	    (*ep)->esize = tp2->size;
--- 1513,1519 ----
      opt0(ep);			/* to make a constant really a constant */
  
      if ((*ep)->nodetype == en_icon)
! 	if (integral(tp2) || tp2->type == bt_pointer || tp2->type == bt_void) {
  	    long            j = (*ep)->v.i;
  	    (*ep)->etype = tp2->type;
  	    (*ep)->esize = tp2->size;
***************
*** 1499,1514 ****
  	fprintf(stderr, "A cast to a narrower type looses accuracy.\n");
      if (tp2->type == bt_pointer && tp1->size < 4 && warning())
  	fprintf(stderr, "A cast from short to pointer is dangerous.\n");
-     /*
-      * The next statement is valid on 68000 architecture, it omits casts
-      * between long, unsigned long, pointer This saves perhaps some memory
-      * and computation time If you don't like it, delete it....
-      */
- 
-     if ((tp1->type == bt_long || tp1->type == bt_ulong || tp1->type == bt_pointer)
- 	&&
- 	(tp2->type == bt_long || tp2->type == bt_ulong || tp2->type == bt_pointer))
- 	return tp2;
  
  
      ep2 = mk_node(en_cast, *ep, NIL_ENODE);
--- 1543,1548 ----
diff -c c68III/expr.h c68III.1/expr.h
*** c68III/expr.h	Mon Feb  4 19:58:23 1991
--- c68III.1/expr.h	Fri Mar  1 10:49:47 1991
***************
*** 50,56 ****
      enum e_node     nodetype;
      enum e_bt       etype;
      long            esize;
!     unsigned char   bit_width, bit_offset;
      union {
  	long            i;
  	double          f;
--- 50,56 ----
      enum e_node     nodetype;
      enum e_bt       etype;
      long            esize;
!     char            bit_width, bit_offset; /* possibly unsigned char */
      union {
  	long            i;
  	double          f;
***************
*** 82,89 ****
      struct enode   *exp;	/* optimizable expression */
      unsigned short  uses;	/* number of uses */
      unsigned short  duses;	/* number of dereferenced uses */
!     char            voidf;	/* cannot optimize flag */
!     char            reg;	/* allocated register */
  };
  
  struct enode   *mk_node();
--- 82,89 ----
      struct enode   *exp;	/* optimizable expression */
      unsigned short  uses;	/* number of uses */
      unsigned short  duses;	/* number of dereferenced uses */
!     short           voidf;	/* cannot optimize flag */
!     short           reg;	/* allocated register */
  };
  
  struct enode   *mk_node();
diff -c c68III/func.c c68III.1/func.c
*** c68III/func.c	Mon Feb  4 19:58:31 1991
--- c68III.1/func.c	Fri Mar  1 10:49:55 1991
***************
*** 271,276 ****
--- 271,277 ----
      struct sym     *sp;
  {
      struct snode   *stmt;
+     int local_total_errors = total_errors;
  #ifdef VERBOSE
      time_t          ltime;
  #endif				/* VERBOSE */
***************
*** 292,297 ****
--- 293,306 ----
      times(&tms_buf);
      ltime = tms_buf.tms_utime;
  #endif				/* VERBOSE */
+ /*
+  * If errors so far, do not try to generate code
+  */
+     if (total_errors > local_total_errors) {
+         cseg();
+         dumplits();
+         return;
+     }
      genfunc(stmt);
  #ifdef VERBOSE
      times(&tms_buf);
diff -c c68III/gen.h c68III.1/gen.h
*** c68III/gen.h	Mon Feb  4 19:58:24 1991
--- c68III.1/gen.h	Fri Mar  1 10:49:48 1991
***************
*** 88,94 ****
--- 88,96 ----
      op_rep, op_smov,
      op_shl, op_shr, op_asr,
      op_fadd, op_fsub, op_fdiv, op_fmul,
+     op_fsubr, op_fdivr,
      op_fld, op_fst, op_fstp, op_fpop,
+     op_fild, op_ftst,
      op_fchs, op_fcompp, op_fnstsw, op_sahf,
      op_label
  };
***************
*** 113,120 ****
  struct amode {
      enum e_am       mode;
      struct enode   *offset;
      char            preg, sreg;
!     unsigned char   deep;
  };
  
  #define NIL_AMODE ( (struct amode *) 0)
--- 115,125 ----
  struct amode {
      enum e_am       mode;
      struct enode   *offset;
+ /*
+  * these chars may be unsigned...
+  */
      char            preg, sreg;
!     char   	    deep;
  };
  
  #define NIL_AMODE ( (struct amode *) 0)
***************
*** 125,131 ****
      enum e_op       opcode;
      struct amode   *oper1, *oper2;
      struct ocode   *fwd, *back;
!     char            length;
  };
  
  /* register naming, special registers */
--- 130,136 ----
      enum e_op       opcode;
      struct amode   *oper1, *oper2;
      struct ocode   *fwd, *back;
!     int             length;
  };
  
  /* register naming, special registers */
diff -c c68III/gen386.c c68III.1/gen386.c
*** c68III/gen386.c	Mon Feb  4 19:58:40 1991
--- c68III.1/gen386.c	Fri Mar  1 10:50:05 1991
***************
*** 91,97 ****
  {
      struct amode   *ap;
      struct enode   *ep;
!     ep = mk_icon((long) 0);
      ep->v.i = i;
      ap = (struct amode *) xalloc((int) sizeof(struct amode));
      ap->mode = am_immed;
--- 91,97 ----
  {
      struct amode   *ap;
      struct enode   *ep;
!     ep = mk_icon(0l);
      ep->v.i = i;
      ap = (struct amode *) xalloc((int) sizeof(struct amode));
      ap->mode = am_immed;
***************
*** 126,135 ****
--- 126,138 ----
      struct amode   *ap2;
  
      if (flags & F_NOVALUE) {
+         /* ap == 0 is allowed in these cases */
          freeop(ap);
          maybe_fppop(ap);
  	return 0;
      }
+     if (ap == 0)
+         fatal("MK_LEGAL: AP == 0");
  
  	switch (ap->mode) {
  	  case am_immed:
***************
*** 155,162 ****
                      g_code(op_fld, 1+ (int) size, ap, NIL_AMODE);
                  else {
                      g_code(op_lea, 4, ap, &ecx_reg, NIL_AMODE);
!                     g_code(op_push, 4, &ecx_reg, NIL_AMODE);
!                     call_library(size == 4 ? "fplds" : "fpldl");
                  }
                  freeop(ap);
                  return &fp_stack;
--- 158,171 ----
                      g_code(op_fld, 1+ (int) size, ap, NIL_AMODE);
                  else {
                      g_code(op_lea, 4, ap, &ecx_reg, NIL_AMODE);
!                     call_library(size == 4 ? ".fplds" : ".fpldl");
! /*
!  * LIBRARY fplds, fpldl
!  *
!  * loads single or double precision FP value on stack
!  * a pointer to the FP value is in %ecx
!  * except %ecx, no registers may be clobbered
!  */
                  }
                  freeop(ap);
                  return &fp_stack;
***************
*** 200,205 ****
--- 209,233 ----
  }
  
  
+ struct enode *
+ mk_add(ep1,ep2)
+ /*
+  * generates added offsets.
+  * ep1, or ep2, or both may be NULL, representing zero offsets
+  */
+     struct enode *ep1,*ep2;
+ {
+     if (ep1 == 0)
+         return ep2;
+     if (ep2 == 0)
+         return ep1;
+     if (ep1->nodetype == en_icon && ep2->nodetype == en_icon) {
+         ep1->v.i += ep2->v.i;
+         return ep1;
+     }
+     return mk_node(en_add,ep1,ep2);
+ }
+ 
  struct amode   *
  g_deref(node, type)
  /*
***************
*** 250,256 ****
   * indx2         indx2      g_code + g_code + indx2
   */
              if (ap1->mode == am_direct && ap2->mode == am_direct) {
!                 ap2->offset = mk_node(en_add,ap1->offset, ap2->offset);
                  return ap2;
              }
              if (ap1->mode == am_direct &&
--- 278,284 ----
   * indx2         indx2      g_code + g_code + indx2
   */
              if (ap1->mode == am_direct && ap2->mode == am_direct) {
!                 ap2->offset = mk_add(ap1->offset, ap2->offset);
                  return ap2;
              }
              if (ap1->mode == am_direct &&
***************
*** 258,270 ****
                  if (ap2->offset == 0)
                      ap2->offset = ap1->offset;
                  else
!                     ap2->offset = mk_node(en_add,ap1->offset,ap2->offset);
                  return ap2;
              }
              if (ap1->mode == am_indx && ap2->mode == am_indx) {
                  if (uses_temp(ap2) && uses_temp(ap1)) {
                      g_code(op_add, 4, mk_reg(ap1->preg), mk_reg(ap2->preg));
!                     ap2->offset=mk_node(en_add,ap1->offset,ap2->offset);
                      freeop(ap1);
                      return ap2;
                  }
--- 286,298 ----
                  if (ap2->offset == 0)
                      ap2->offset = ap1->offset;
                  else
!                     ap2->offset = mk_add(ap1->offset,ap2->offset);
                  return ap2;
              }
              if (ap1->mode == am_indx && ap2->mode == am_indx) {
                  if (uses_temp(ap2) && uses_temp(ap1)) {
                      g_code(op_add, 4, mk_reg(ap1->preg), mk_reg(ap2->preg));
!                     ap2->offset=mk_add(ap1->offset,ap2->offset);
                      freeop(ap1);
                      return ap2;
                  }
***************
*** 273,279 ****
                      ap2->sreg = ap2->preg;
                      ap2->mode = am_indx2;
                      ap2->preg = ap1->preg;
!                     ap2->offset=mk_node(en_add,ap1->offset,ap2->offset);
                      return ap2;
                  }
                  if (uses_temp(ap1)) {
--- 301,307 ----
                      ap2->sreg = ap2->preg;
                      ap2->mode = am_indx2;
                      ap2->preg = ap1->preg;
!                     ap2->offset=mk_add(ap1->offset,ap2->offset);
                      return ap2;
                  }
                  if (uses_temp(ap1)) {
***************
*** 281,287 ****
                      ap1->sreg = ap1->preg;
                      ap1->mode = am_indx2;
                      ap1->preg = ap2->preg;
!                     ap1->offset=mk_node(en_add,ap1->offset,ap2->offset);
                      return ap1;
                  }
                  /* do not create (%esi,%edi etc) */
--- 309,315 ----
                      ap1->sreg = ap1->preg;
                      ap1->mode = am_indx2;
                      ap1->preg = ap2->preg;
!                     ap1->offset=mk_add(ap1->offset,ap2->offset);
                      return ap1;
                  }
                  /* do not create (%esi,%edi etc) */
***************
*** 290,296 ****
                  g_code(op_add, 4, mk_reg(ap2->preg), ap3);
                  ap3 = copy_addr(ap3);
                  ap3->mode = am_indx;
!                 ap3->offset=mk_node(en_add,ap1->offset,ap2->offset);
                  return ap3;
              }
              if (ap1->mode == am_indx2 && ap2->mode == am_indx) {
--- 318,324 ----
                  g_code(op_add, 4, mk_reg(ap2->preg), ap3);
                  ap3 = copy_addr(ap3);
                  ap3->mode = am_indx;
!                 ap3->offset=mk_add(ap1->offset,ap2->offset);
                  return ap3;
              }
              if (ap1->mode == am_indx2 && ap2->mode == am_indx) {
***************
*** 301,317 ****
                      ap2->sreg = ap2->preg;
                      ap2->preg = ap1->preg;
                      ap2->mode = am_indx2;
!                     ap2->offset=mk_node(en_add,ap1->offset,ap2->offset);
                      return ap2;
                  }
                  g_code(op_mov, 4, mk_reg(ap2->preg), mk_reg(ap1->sreg));
!                 ap1->offset=mk_node(en_add,ap1->offset,ap2->offset);
                  return ap1;
              }
              if (ap1->mode == am_indx && ap2->mode == am_indx2) {
                  freeop(ap1);
                  g_code(op_add, 4, mk_reg(ap1->preg), mk_reg(ap2->sreg));
!                 ap1->offset=mk_node(en_add,ap1->offset,ap2->offset);
                  return ap2;
              }
              if (ap1->mode == am_indx2 && ap2->mode == am_indx2) {
--- 329,345 ----
                      ap2->sreg = ap2->preg;
                      ap2->preg = ap1->preg;
                      ap2->mode = am_indx2;
!                     ap2->offset=mk_add(ap1->offset,ap2->offset);
                      return ap2;
                  }
                  g_code(op_mov, 4, mk_reg(ap2->preg), mk_reg(ap1->sreg));
!                 ap1->offset=mk_add(ap1->offset,ap2->offset);
                  return ap1;
              }
              if (ap1->mode == am_indx && ap2->mode == am_indx2) {
                  freeop(ap1);
                  g_code(op_add, 4, mk_reg(ap1->preg), mk_reg(ap2->sreg));
!                 ap1->offset=mk_add(ap1->offset,ap2->offset);
                  return ap2;
              }
              if (ap1->mode == am_indx2 && ap2->mode == am_indx2) {
***************
*** 319,325 ****
                  ap3 = mk_reg(ap2->sreg);
                  g_code(op_add, 4, mk_reg(ap1->preg), ap3);
                  g_code(op_add, 4, mk_reg(ap1->sreg), ap3);
!                 ap2->offset=mk_node(en_add,ap1->offset,ap2->offset);
                  return ap2;
              }
              fatal ("G_DEREF COMBINE");                
--- 347,353 ----
                  ap3 = mk_reg(ap2->sreg);
                  g_code(op_add, 4, mk_reg(ap1->preg), ap3);
                  g_code(op_add, 4, mk_reg(ap1->sreg), ap3);
!                 ap2->offset=mk_add(ap1->offset,ap2->offset);
                  return ap2;
              }
              fatal ("G_DEREF COMBINE");                
***************
*** 404,410 ****
          if (fpu_option)
  	    g_code(op_fchs, 0, NIL_AMODE, NIL_AMODE);
          else
!             call_library("fpneg");
          return mk_legal(&fp_stack, flags, 8l);
      }
      fatal("g_unary: illegal type or operation");
--- 432,443 ----
          if (fpu_option)
  	    g_code(op_fchs, 0, NIL_AMODE, NIL_AMODE);
          else
!             call_library(".fpneg");
! /*
!  * LIBRARY fpneg
!  * negates the number on top of the FP stack
!  * only %ecx may be clobbered
!  */
          return mk_legal(&fp_stack, flags, 8l);
      }
      fatal("g_unary: illegal type or operation");
***************
*** 434,447 ****
        case bt_pointer:
  	ap1 = g_expr(node->v.p[0], F_REG | F_VOL);
  	ap2 = g_expr(node->v.p[1], f);
! 	validate(ap1);		/* in case push occurred */
  	g_code(op, (int) node->esize, ap2, ap1);
  	freeop(ap2);
  	return mk_legal(ap1, flags, node->esize);
        case bt_float:
        case bt_double:
-         (void) g_expr(node->v.p[1], F_FPSTACK);
          (void) g_expr(node->v.p[0], F_FPSTACK);
          if (fpu_option)
              switch (op) {
                case op_add:
--- 467,480 ----
        case bt_pointer:
  	ap1 = g_expr(node->v.p[0], F_REG | F_VOL);
  	ap2 = g_expr(node->v.p[1], f);
! 	validate(ap1);
  	g_code(op, (int) node->esize, ap2, ap1);
  	freeop(ap2);
  	return mk_legal(ap1, flags, node->esize);
        case bt_float:
        case bt_double:
          (void) g_expr(node->v.p[0], F_FPSTACK);
+         (void) g_expr(node->v.p[1], F_FPSTACK);
          if (fpu_option)
              switch (op) {
                case op_add:
***************
*** 448,460 ****
                  g_code(op_fadd, 0, NIL_AMODE, NIL_AMODE);
                  break;
                case op_sub:
!                 g_code(op_fsub, 0, NIL_AMODE, NIL_AMODE);
                  break;
                case op_imul:
                  g_code(op_fmul, 0, NIL_AMODE, NIL_AMODE);
                  break;
                case op_idiv:
!                 g_code(op_fdiv, 0, NIL_AMODE, NIL_AMODE);
                  break;
                default:
                  fatal("G_BIN ILLEGAL OP");
--- 481,493 ----
                  g_code(op_fadd, 0, NIL_AMODE, NIL_AMODE);
                  break;
                case op_sub:
!                 g_code(op_fsubr,0, NIL_AMODE, NIL_AMODE);
                  break;
                case op_imul:
                  g_code(op_fmul, 0, NIL_AMODE, NIL_AMODE);
                  break;
                case op_idiv:
!                 g_code(op_fdivr,0, NIL_AMODE, NIL_AMODE);
                  break;
                default:
                  fatal("G_BIN ILLEGAL OP");
***************
*** 461,477 ****
              }
  	else
              switch (op) {
                case op_add:
!                 call_library("fpadd");
                  break;
                case op_sub:
!                 call_library("fpsub");
                  break;
                case op_imul:
!                 call_library("fpmult");
                  break;
                case op_idiv:
!                 call_library("fpdiv");
                  break;
                default:
                  fatal("G_BIN ILLEGAL OP");
--- 494,518 ----
              }
  	else
              switch (op) {
+ /*
+  * LIBRARY fpadd fpsub fpmult fpdiv
+  * if the top elements of the FP stack are a b .....
+  * the stack is c ..... after this call, where
+  * c = b+a, b-a, b/a, or b*a
+  *
+  * only %ecx may be clobbered
+  */
                case op_add:
!                 call_library(".fpadd");
                  break;
                case op_sub:
!                 call_library(".fpsub");
                  break;
                case op_imul:
!                 call_library(".fpmult");
                  break;
                case op_idiv:
!                 call_library(".fpdiv");
                  break;
                default:
                  fatal("G_BIN ILLEGAL OP");
***************
*** 507,513 ****
              ap1 = 0;
  	ap2 = g_expr(node->v.p[0], F_MEM | F_REG);
          if (ap1) {
! 	    validate(ap1);		/* in case push occurred */
              g_code(op_mov, (int) node->esize, ap2, ap1);
          }
          g_code(op, (int) node->esize, mk_immed(node->v.p[1]->v.i), ap2);
--- 548,554 ----
              ap1 = 0;
  	ap2 = g_expr(node->v.p[0], F_MEM | F_REG);
          if (ap1) {
! 	    validate(ap1);
              g_code(op_mov, (int) node->esize, ap2, ap1);
          }
          g_code(op, (int) node->esize, mk_immed(node->v.p[1]->v.i), ap2);
***************
*** 548,554 ****
  	ap1 = g_expr(node->v.p[0], f1);
          ap2 = g_expr(node->v.p[1], f2);
          ap3 = &ecx_reg;
! 	validate(ap1);		/* in case push occurred */
          g_code(op_mov, (int) node->esize, ap1, ap3);
  	g_code(op, (int) node->esize, ap2, ap3);
          g_code(op_mov, (int) node->esize, ap3, ap1);
--- 589,595 ----
  	ap1 = g_expr(node->v.p[0], f1);
          ap2 = g_expr(node->v.p[1], f2);
          ap3 = &ecx_reg;
! 	validate(ap1);
          g_code(op_mov, (int) node->esize, ap1, ap3);
  	g_code(op, (int) node->esize, ap2, ap3);
          g_code(op_mov, (int) node->esize, ap3, ap1);
***************
*** 571,578 ****
              g_code (op_fld, f ? 5 : 9, ap1, NIL_AMODE);
          else {
              g_code (op_lea, 4, ap1, &ecx_reg);
!             g_code (op_push, 4, &ecx_reg, NIL_AMODE);
!             call_library(f ? "fplds" : "fpldl");
          }
          if (fpu_option) {
              switch (op) {
--- 612,618 ----
              g_code (op_fld, f ? 5 : 9, ap1, NIL_AMODE);
          else {
              g_code (op_lea, 4, ap1, &ecx_reg);
!             call_library(f ? ".fplds" : ".fpldl");
          }
          if (fpu_option) {
              switch (op) {
***************
*** 591,625 ****
                default:
                  fatal("G_ASBIN ILLEGAL OP");
              }
!             if (flags & F_NOVALUE)
                  g_code(op_fstp, f ? 5 : 9, ap1, NIL_AMODE);
!             else
                  g_code(op_fst,  f ? 5 : 9, ap1, NIL_AMODE);
  	 } else {
              switch (op) {
                case op_add:
!                 call_library("fpadd");
                  break;
                case op_sub:
!                 call_library("fpsub");
                  break;
                case op_imul:
!                 call_library("fpmult");
                  break;
                case op_idiv:
!                 call_library("fpdiv");
                  break;
                default:
                  fatal("G_ASBIN ILLEGAL OP");
             }
-            if (!(flags & F_NOVALUE))
-                call_library("fpdup");
             g_code(op_lea, 4, ap1, &ecx_reg);
!            g_code(op_push, 4, &ecx_reg, NIL_AMODE);
!            call_library(f ? "fpsts" : "fpstl");
  	}
          freeop(ap1);
!         return mk_legal(&fp_stack, flags, node->esize);
      }
      fatal("g_asbin illegal type");
      /* NOTREACHED */
--- 631,681 ----
                default:
                  fatal("G_ASBIN ILLEGAL OP");
              }
!             if (flags & F_NOVALUE) {
                  g_code(op_fstp, f ? 5 : 9, ap1, NIL_AMODE);
!                 ap2 = 0;
!             } else {
                  g_code(op_fst,  f ? 5 : 9, ap1, NIL_AMODE);
+                 ap2 = &fp_stack;
+             }
  	 } else {
              switch (op) {
                case op_add:
!                 call_library(".fpadd");
                  break;
                case op_sub:
!                 call_library(".fpsub");
                  break;
                case op_imul:
!                 call_library(".fpmult");
                  break;
                case op_idiv:
!                 call_library(".fpdiv");
                  break;
                default:
                  fatal("G_ASBIN ILLEGAL OP");
             }
             g_code(op_lea, 4, ap1, &ecx_reg);
!            if (flags & F_NOVALUE) {
!                ap2 = 0;
!                call_library (f ? ".fpstps" : ".fpstpl");
! /*
!  * LIBRARY fpstps, fpstpl
!  * Store the top of the floating point stack into the location addressed
!  * by %ecx. Only %ecx may be clobbered.
!  * pop the top of the stack thereafter.
!  */
!            } else {
!                ap2 = &fp_stack;
!                call_library(f ? ".fpsts" : ".fpstl");
! /*
!  * LIBRARY fpsts, fpstl
!  * same as fpstps, fpstpl, but do not touch the FP stack
!  */
!            }
  	}
          freeop(ap1);
!         return mk_legal(ap2, flags, node->esize);
      }
      fatal("g_asbin illegal type");
      /* NOTREACHED */
***************
*** 821,826 ****
--- 877,883 ----
        case bt_ushort:
          ap1 = g_expr(node->v.p[0], F_REG | F_VOL);
          ap2 = g_expr(node->v.p[1], F_ALL);
+         validate(ap1);
          if (ap2->mode == am_immed)
              g_code(op_shl, (int) node->esize, ap2, ap1);
          else {
***************
*** 853,858 ****
--- 910,916 ----
        case bt_ushort:
          ap1 = g_expr(node->v.p[0], F_MEM | F_REG);
          ap2 = g_expr(node->v.p[1], F_ALL);
+         validate(ap1);
          if (ap2->mode == am_immed)
              g_code(op_shl, (int) node->esize, ap2, ap1);
          else {
***************
*** 888,893 ****
--- 946,952 ----
        case bt_ushort:
          ap1 = g_expr(node->v.p[0], F_REG | F_VOL);
          ap2 = g_expr(node->v.p[1], F_ALL);
+         validate(ap1);
          if (ap2->mode == am_immed)
              g_code(op,     (int) node->esize, ap2, ap1);
          else {
***************
*** 923,928 ****
--- 982,988 ----
        case bt_ushort:
          ap1 = g_expr(node->v.p[0], F_MEM | F_REG);
          ap2 = g_expr(node->v.p[1], F_ALL);
+         validate(ap1);
          if (ap2->mode == am_immed)
              g_code(op,     (int) node->esize, ap2, ap1);
          else {
***************
*** 948,959 ****
      unsigned int    false_label, end_label;
      long size=node->esize;
      int flagx;
  
!     if (node->etype == bt_float || node->etype == bt_double)
!         flagx = F_FPSTACK;
!     else
!         flagx = F_REG | F_VOL;
! 
      false_label = nextlabel++;
      end_label = nextlabel++;
  
--- 1008,1033 ----
      unsigned int    false_label, end_label;
      long size=node->esize;
      int flagx;
+     int result_is_void;
  
!     switch (node->etype) {
!         case bt_float:
!         case bt_double:
!           flagx = F_FPSTACK;
!           result_is_void =0;
!           break;
!         case bt_void:
!           flagx = F_ALL | F_NOVALUE;
!           result_is_void = 1;
!           break;
!         case bt_struct:
!         case bt_union:
!           size = 4;
!           /*FALLTHROUGH*/
!         default:
!           flagx = F_REG | F_VOL;
!     }
!           
      false_label = nextlabel++;
      end_label = nextlabel++;
  
***************
*** 977,983 ****
  
      ap2 = g_expr(node->v.p[1], flagx);
  
!     if (! equal_address(ap1,ap2))
         fatal("G_HOOK: INCONSISTENCY");
  
      g_label(end_label);
--- 1051,1057 ----
  
      ap2 = g_expr(node->v.p[1], flagx);
  
!     if (!result_is_void && !equal_address(ap1,ap2))
         fatal("G_HOOK: INCONSISTENCY");
  
      g_label(end_label);
***************
*** 1100,1130 ****
      }
      if (node->etype == bt_double || node->etype == bt_float) {
        int f = node->etype == bt_float;
        if (fpu_option) {
! 	(void) g_expr(node->v.p[1], F_FPSTACK);
!         ap1 = g_expr(node->v.p[0], F_MEM);
!         if (flags & F_NOVALUE)
              g_code(op_fstp, f ? 5 : 9, ap1, NIL_AMODE);
!         else
              g_code(op_fst, f ? 5 : 9, ap1, NIL_AMODE);
!         freeop(ap1);
        } else {
!         /*
!          * If we need the result, we must duplicate the top of the
!          * floating point stack
!          */
!         if (!(flags & F_NOVALUE))
!             call_library("fpdup");
!         temp_inv();
!         (void) g_expr(node->v.p[1], F_FPSTACK);
!         (void) push_param(node->v.p[0]->v.p[0]);
!         /*
!          * fpsts/fpstl are assumed to clean the stack and to save
!          * all clobbered registers
!          */
!         call_library(f ? "fpsts" : "fpstl");
        }
!       return mk_legal(&fp_stack, flags, 8l);
      }
      /*
       * (uns.) char, (uns.) short, (uns.) long
--- 1174,1201 ----
      }
      if (node->etype == bt_double || node->etype == bt_float) {
        int f = node->etype == bt_float;
+       (void) g_expr(node->v.p[1], F_FPSTACK);
+       ap1 = g_expr(node->v.p[0], F_MEM);
+       freeop(ap1);
        if (fpu_option) {
!         if (flags & F_NOVALUE) {
              g_code(op_fstp, f ? 5 : 9, ap1, NIL_AMODE);
!             ap1 = 0;
!         } else {
              g_code(op_fst, f ? 5 : 9, ap1, NIL_AMODE);
!             ap1 = &fp_stack;
!         }
        } else {
!         g_code(op_lea, 4, ap1, &ecx_reg);
!         if (flags & F_NOVALUE) {
!             ap1 = 0;
!             call_library(f ? ".fpstps" : ".fpstpl");
!         } else {
!             ap1 = &fp_stack;
!             call_library(f ? ".fpsts" : ".fpstl");
!         }
        }
!       return mk_legal(ap1, flags, 8l);
      }
      /*
       * (uns.) char, (uns.) short, (uns.) long
***************
*** 1178,1185 ****
            ap->offset = 0;
            g_code(op_fstp, 9, ap, NIL_AMODE);
          } else {
!           g_code(op_push, 4, &esp_reg, NIL_AMODE);
!           call_library("fpstl");
          }
        return 8;
      }
--- 1249,1256 ----
            ap->offset = 0;
            g_code(op_fstp, 9, ap, NIL_AMODE);
          } else {
!           g_code(op_mov, 4, &esp_reg, &ecx_reg);
!           call_library(".fpstpl");
          }
        return 8;
      }
***************
*** 1253,1259 ****
          if (fpu_option)
             g_code(op_fpop, 0, NIL_AMODE, NIL_AMODE);
          else
!            call_library("fppop");
  }
  
  struct amode   *
--- 1324,1330 ----
          if (fpu_option)
             g_code(op_fpop, 0, NIL_AMODE, NIL_AMODE);
          else
!            call_library(".fppop");
  }
  
  struct amode   *
***************
*** 1312,1317 ****
--- 1383,1389 ----
   */
  {
      long	   siz1, siz2;
+     struct amode   *ap1;
  
      if (flags & F_NOVALUE) {
          freeop(ap);
***************
*** 1342,1354 ****
            case bt_ulong:
            case bt_pointer:
  /*
!  * LIBRARY SPECIFICATION:
   *
!  * fpldi(fpldu) take an (unsigned) long item from the stack, convert it
!  * to double and push the value onto the floating point stack
   */
!             g_code(op_push, 4, ap, NIL_AMODE);
!             call_library(typ1 == bt_long ? "fpldi" : "fpldu");
              freeop(ap);
              return mk_legal(&fp_stack, flags, siz2);
          }
--- 1414,1457 ----
            case bt_ulong:
            case bt_pointer:
  /*
!  * LIBRARY fpldi, fpldu
   *
!  * fpldi and fpldu convert the long resp. unsigned long item in
!  * %ecx to double and push that value onto the floating point stack.
!  * No register other than %ecx may be clobbered.
   */
! /*
!  * For the conversion signed long --> float/double, there is
!  * a 387 instruction
!  */
!             if (typ1==bt_long && fpu_option) {
!                 if (ap->mode == am_direct || ap->mode == am_indx ||
!                     ap->mode == am_indx2) {
! /*
!  * FPU-code for a signed long that is in memory
!  */
! 		    g_code(op_fild, 4, ap, NIL_AMODE);
! 	        } else {
! /*
!  * FPU-code for a signed long that is in a register:
!  * the value is written to -4(%esp) and loaded from there
!  * since there is no direct path between CPU and FPU registers.
!  */
!                     ap1 = mk_reg(ESP);
! 	            ap1->mode = am_indx;
!                     ap1->offset = mk_icon(-4l);
! 		    g_code(op_mov, 4, ap, ap1);
! 		    g_code(op_fild, 4, ap1, NIL_AMODE);
! 	 	}
! 	        freeop(ap);
! 		return mk_legal(&fp_stack, flags, siz2);
! 	    }
! /*
!  * The general case (no inline-FPU code or unsigned conversion)
!  */
! 
!             g_code(op_mov, 4, ap, &ecx_reg);
!             call_library(typ1 == bt_long ? ".fpldi" : ".fpldu");
              freeop(ap);
              return mk_legal(&fp_stack, flags, siz2);
          }
***************
*** 1362,1372 ****
              (void) mk_legal(ap, F_FPSTACK, siz1);
              ap = get_register();
  /*
!  * LIBRARY SPECIFICATION:
!  * fpsti(fpstu) pop the top of the floating point stack, convert it
!  * to (unsigned) long and return the value in %ecx
   */
!             call_library("fpsti");
              g_code (op_mov, 1, &ecx_reg, ap);
              return mk_legal(ap, flags, 1l);
            case bt_uchar:
--- 1465,1476 ----
              (void) mk_legal(ap, F_FPSTACK, siz1);
              ap = get_register();
  /*
!  * LIBRARY fpsti fpstu
!  * These functions convert the top of the FP stack to long resp. unsigned long,
!  * and return the value in %ecx. No register other than %ecx may be clobbered.
!  * The top of the FP Stack is popped thereafter
   */
!             call_library(".fpsti");
              g_code (op_mov, 1, &ecx_reg, ap);
              return mk_legal(ap, flags, 1l);
            case bt_uchar:
***************
*** 1386,1392 ****
  	  case bt_double:
              (void) mk_legal(ap, F_FPSTACK, siz1);
              ap = get_register();
!             call_library("fpsti");
  	    g_code(op_mov, 2, &ecx_reg, ap);
              return mk_legal(ap, flags, 2l);
  	  case bt_uchar:
--- 1490,1496 ----
  	  case bt_double:
              (void) mk_legal(ap, F_FPSTACK, siz1);
              ap = get_register();
!             call_library(".fpsti");
  	    g_code(op_mov, 2, &ecx_reg, ap);
              return mk_legal(ap, flags, 2l);
  	  case bt_uchar:
***************
*** 1413,1419 ****
            case bt_double:
              (void) mk_legal(ap, F_FPSTACK, siz1);
              ap = get_register();
!             call_library(typ2 == bt_long ? "fpsti" : "fpstu");
              g_code(op_mov, 4, &ecx_reg, ap);
              return mk_legal(ap, flags, 4l);
  	  case bt_uchar:
--- 1517,1523 ----
            case bt_double:
              (void) mk_legal(ap, F_FPSTACK, siz1);
              ap = get_register();
!             call_library(typ2 == bt_long ? ".fpsti" : ".fpstu");
              g_code(op_mov, 4, &ecx_reg, ap);
              return mk_legal(ap, flags, 4l);
  	  case bt_uchar:
***************
*** 1453,1466 ****
  {
      struct amode   *ap1, *ap2;
      unsigned int    lab0, lab1;
      if (node == 0) {
  	fatal("null node in g_expr");
      }
      if (tst_const(node)) {
  	ap1 = (struct amode *) xalloc((int) sizeof(struct amode));
  	ap1->mode = am_immed;
  	ap1->offset = node;
! 	return mk_legal(ap1, flags, node->esize);
      }
      switch (node->nodetype) {
        case en_autocon:
--- 1557,1574 ----
  {
      struct amode   *ap1, *ap2;
      unsigned int    lab0, lab1;
+     long size;
+     enum e_bt type;
      if (node == 0) {
  	fatal("null node in g_expr");
      }
+     size = node->esize;
+     type = node->etype;
      if (tst_const(node)) {
  	ap1 = (struct amode *) xalloc((int) sizeof(struct amode));
  	ap1->mode = am_immed;
  	ap1->offset = node;
! 	return mk_legal(ap1, flags, size);
      }
      switch (node->nodetype) {
        case en_autocon:
***************
*** 1470,1482 ****
  	    ap2->preg = FRAMEPTR;	/* frame pointer */
  	    ap2->offset = node;	/* use as constant node */
  	    g_code(op_lea, 4, ap2, ap1);
! 	return mk_legal(ap1, flags, node->esize);
        case en_tempref:
          ap1=mk_reg((int) node->v.i);
!         return mk_legal(ap1, flags, node->esize);
        case en_ref:
!         ap1=g_deref(node->v.p[0], node->etype);
!         return mk_legal(ap1, flags, node->esize);
        case en_fieldref:
          return g_fderef(node, flags);
        case en_uminus:
--- 1578,1593 ----
  	    ap2->preg = FRAMEPTR;	/* frame pointer */
  	    ap2->offset = node;	/* use as constant node */
  	    g_code(op_lea, 4, ap2, ap1);
! 	return mk_legal(ap1, flags, size);
        case en_tempref:
          ap1=mk_reg((int) node->v.i);
!         return mk_legal(ap1, flags, size);
        case en_ref:
!         ap1=g_deref(node->v.p[0], type);
!         if (type == bt_struct || type == bt_union)
!             return mk_legal(ap1, flags, 4l);
!         else
!             return mk_legal(ap1, flags, node->esize);
        case en_fieldref:
          return g_fderef(node, flags);
        case en_uminus:
***************
*** 1549,1555 ****
  	g_label(lab0);
  	g_code(op_mov, 4, mk_immed(0l), ap1);
  	g_label(lab1);
! 	return mk_legal(ap1, flags, node->esize);
        case en_void:
  	freeop(g_expr(node->v.p[0], F_ALL | F_NOVALUE));
  	return g_expr(node->v.p[1], flags);
--- 1660,1666 ----
  	g_label(lab0);
  	g_code(op_mov, 4, mk_immed(0l), ap1);
  	g_label(lab1);
! 	return mk_legal(ap1, flags, size);
        case en_void:
  	freeop(g_expr(node->v.p[0], F_ALL | F_NOVALUE));
  	return g_expr(node->v.p[1], flags);
***************
*** 1591,1608 ****
   */
  {
      enum e_node     typ1 = node->nodetype;
!     enum e_node     typ2;
!     if (typ1 == en_icon || typ1 == en_nacon || typ1 == en_labcon)
! 	return 1;
! 
!     if (typ1 == en_add || typ1 == en_sub) {
! 	typ1 = node->v.p[0]->nodetype;
! 	typ2 = node->v.p[1]->nodetype;
! 	if (((typ1 == en_nacon || typ1 == en_labcon) && typ2 == en_icon) ||
! 	    ((typ2 == en_nacon || typ2 == en_labcon) && typ1 == en_icon))
! 	    return 1;
      }
-     return 0;
  }
  
  
--- 1702,1721 ----
   */
  {
      enum e_node     typ1 = node->nodetype;
!     switch (typ1) {
!       case en_icon:
!       case en_nacon:
!       case en_labcon:
!         return 1;
!       case en_add:
!       case en_sub:
!         return tst_const(node->v.p[0]) && tst_const(node->v.p[1]);
!       case en_cast:
!       case en_uminus:
!         return tst_const(node->v.p[0]);
!       default:
!         return 0;
      }
  }
  
  
***************
*** 1641,1654 ****
          (void) g_expr(node->v.p[1], F_FPSTACK);
          (void) g_expr(node->v.p[0], F_FPSTACK);
          if (fpu_option) {
!             if (reg_in_use[0]) 
!                 temp_inv(); /* %ax clobbered */
              g_code(op_fcompp, 0, NIL_AMODE, NIL_AMODE);
              g_code(op_fnstsw, 0, &ax_reg,   NIL_AMODE);
              g_code(op_sahf,   0, NIL_AMODE, NIL_AMODE);
              return 1;
          } else {
!             call_library("fpcmp");
              ap1 = &ecx_reg;
              g_code(op_test, 4, ap1, ap1);
              return 0;
--- 1754,1777 ----
          (void) g_expr(node->v.p[1], F_FPSTACK);
          (void) g_expr(node->v.p[0], F_FPSTACK);
          if (fpu_option) {
!             if (reg_in_use[0] >= 0) 
!                 temp_inv();
              g_code(op_fcompp, 0, NIL_AMODE, NIL_AMODE);
              g_code(op_fnstsw, 0, &ax_reg,   NIL_AMODE);
              g_code(op_sahf,   0, NIL_AMODE, NIL_AMODE);
              return 1;
          } else {
!             call_library(".fpcmp");
! /*
!  * LIBRARY fpcmp
!  * If the stack is a b .... before this operation, compare a with b.
!  * Return as result in %ecx:
!  * -1, if a < b
!  *  0, if a == b
!  *  1, if a > b
!  *
!  * Pop a and b from the FP stack thereafter
!  */
              ap1 = &ecx_reg;
              g_code(op_test, 4, ap1, ap1);
              return 0;
***************
*** 1733,1744 ****
            case bt_double:
            case bt_float:
              (void) g_expr(node, F_FPSTACK);
!             call_library("fptst");
!             ap1 = &ecx_reg;
!             g_code(op_pop, 4, ap1, NIL_AMODE);
!             g_code(op_test, 4, ap1, ap1);
              g_code(op_jne, 0, mk_label(label), NIL_AMODE);
-             freeop(ap1);
              return;
          }
          fatal ("truejp: illegal type");
--- 1856,1884 ----
            case bt_double:
            case bt_float:
              (void) g_expr(node, F_FPSTACK);
! 	    if (fpu_option) {
!                 if (reg_in_use[0] >= 0)
!                     temp_inv();
!                 g_code(op_ftst, 0, NIL_AMODE, NIL_AMODE);
!                 g_code(op_fnstsw, 0, &ax_reg, NIL_AMODE);
! 		g_code(op_fpop, 0, NIL_AMODE, NIL_AMODE);
!                 g_code(op_sahf, 0, NIL_AMODE, NIL_AMODE);
!             } else {
!                 call_library(".fptst");
!                 ap1 = &ecx_reg;
!                 g_code(op_test, 4, ap1, ap1);
!             }
! /*
!  * LIBRARY fptst
!  *
!  * Return in %ecx
!  *
!  * 0, if the top of the FP stack is == 0
!  * 1, if the top of the FP stack is != 0
!  *
!  * Pop the top of the FP stack thereafter.
!  */
              g_code(op_jne, 0, mk_label(label), NIL_AMODE);
              return;
          }
          fatal ("truejp: illegal type");
***************
*** 1821,1830 ****
           case bt_float:
           case bt_double:
             (void) g_expr(node, F_FPSTACK);
!            call_library("fptst");
!            ap = &ecx_reg;
!            g_code(op_pop, 4, ap, NIL_AMODE);
!            g_code(op_test, 4, ap, ap);
             g_code(op_je, 0, mk_label(label), NIL_AMODE);
             return;
          }
--- 1961,1978 ----
           case bt_float:
           case bt_double:
             (void) g_expr(node, F_FPSTACK);
! 	    if (fpu_option) {
!                 if (reg_in_use[0] >= 0)
!                     temp_inv();
!                 g_code(op_ftst, 0, NIL_AMODE, NIL_AMODE);
!                 g_code(op_fnstsw, 0, &ax_reg, NIL_AMODE);
! 		g_code(op_fpop, 0, NIL_AMODE, NIL_AMODE);
!                 g_code(op_sahf, 0, NIL_AMODE, NIL_AMODE);
!             } else {
!                 call_library(".fptst");
!                 ap = &ecx_reg;
!                 g_code(op_test, 4, ap, ap);
!             }
             g_code(op_je, 0, mk_label(label), NIL_AMODE);
             return;
          }
