diff -c c68III/gen68k.c c68III.1/gen68k.c
*** c68III/gen68k.c	Mon Feb  4 19:58:49 1991
--- c68III.1/gen68k.c	Fri Mar  1 10:50:13 1991
***************
*** 78,84 ****
  {
      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;
--- 78,84 ----
  {
      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;
***************
*** 206,213 ****
  g_index(node)
  /*
   * generate code to evaluate an index node and return the addressing
!  * mode of the result. This routine takes no flags since it is only called
!  * when g_deref sees en_add and g_deref does the mk_legal.
   */
      struct enode   *node;
  {
--- 206,212 ----
  g_index(node)
  /*
   * generate code to evaluate an index node and return the addressing
!  * mode of the result.
   */
      struct enode   *node;
  {
***************
*** 223,229 ****
  	    ap1 = copy_addr(ap1);
  	    ap1->sreg = node->v.p[0]->v.i;
  	    ap1->mode = am_indx2;	/* 0(Ax,Dx) */
! 	    ap1->offset = mk_icon((long) 0);
  	    return ap1;
  	} else {
  	    /* first node is address register */
--- 222,228 ----
  	    ap1 = copy_addr(ap1);
  	    ap1->sreg = node->v.p[0]->v.i;
  	    ap1->mode = am_indx2;	/* 0(Ax,Dx) */
! 	    ap1->offset = mk_icon(0l);
  	    return ap1;
  	} else {
  	    /* first node is address register */
***************
*** 239,245 ****
  		ap1->mode = am_indx3;
  		ap1->sreg = ap2->preg;
  	    }
! 	    ap1->offset = mk_icon((long) 0);
  	    return ap1;
  	}
      }
--- 238,244 ----
  		ap1->mode = am_indx3;
  		ap1->sreg = ap2->preg;
  	    }
! 	    ap1->offset = mk_icon(0l);
  	    return ap1;
  	}
      }
***************
*** 276,282 ****
  	    ap1->mode = am_indx2;
  	    ap1->sreg = ap2->preg;
  	    ap1->deep = ap2->deep;
! 	    ap1->offset = mk_icon((long) 0);
  	    return ap1;
  	}
  	if (ap2->mode == am_areg) {
--- 275,281 ----
  	    ap1->mode = am_indx2;
  	    ap1->sreg = ap2->preg;
  	    ap1->deep = ap2->deep;
! 	    ap1->offset = mk_icon(0l);
  	    return ap1;
  	}
  	if (ap2->mode == am_areg) {
***************
*** 284,290 ****
  	    ap1->mode = am_indx3;
  	    ap1->sreg = ap2->preg;
  	    ap1->deep = ap2->deep;
! 	    ap1->offset = mk_icon((long) 0);
  	    return ap1;
  	}
  	if (ap2->mode == am_immed && (!isshort(ap2->offset)))
--- 283,289 ----
  	    ap1->mode = am_indx3;
  	    ap1->sreg = ap2->preg;
  	    ap1->deep = ap2->deep;
! 	    ap1->offset = mk_icon(0l);
  	    return ap1;
  	}
  	if (ap2->mode == am_immed && (!isshort(ap2->offset)))
***************
*** 298,304 ****
  	ap1 = copy_addr(ap1);
  	ap1->mode = am_indx2;
  	ap1->sreg = ap2->preg;
! 	ap1->offset = mk_icon((long) 0);
  	return ap1;
      }
      if (ap1->mode == am_immed && ap2->mode == am_immed) {
--- 297,303 ----
  	ap1 = copy_addr(ap1);
  	ap1->mode = am_indx2;
  	ap1->sreg = ap2->preg;
! 	ap1->offset = mk_icon(0l);
  	return ap1;
      }
      if (ap1->mode == am_immed && ap2->mode == am_immed) {
***************
*** 323,376 ****
  }
  
  struct amode   *
! g_deref(node, flags)
  /*
   * return the addressing mode of a dereferenced node.
   */
!     struct enode   *node;
!     int             flags;
  {
      struct amode   *ap1;
!     long            size;
!     size = node->esize;
!     if (node->v.p[0]->nodetype == en_add) {
! 	return mk_legal(g_index(node->v.p[0]), flags, size);
      }
!     if (node->v.p[0]->nodetype == en_autocon) {
! 	if (node->v.p[0]->v.i >= -32768 && node->v.p[0]->v.i < 32767) {
  	    ap1 = (struct amode *) xalloc((int) sizeof(struct amode));
  	    ap1->mode = am_indx;
  	    ap1->preg = 6;
! 	    ap1->offset = mk_icon((long) node->v.p[0]->v.i);
  	} else {
  	    ap1 = temp_addr();
! 	    g_code(op_move, 4, mk_immed((long) node->v.p[0]->v.i), ap1);
  	    g_code(op_add, 4, mk_reg(FRAMEPTR), ap1);
  	    ap1 = copy_addr(ap1);
  	    ap1->mode = am_ind;
  	}
! 	return mk_legal(ap1, flags, size);
      }
      /* special 68000 instructions */
!     if (node->v.p[0]->nodetype == en_ainc
! 	&& node->v.p[0]->v.p[1]->v.i == size
! 	&& node->v.p[0]->v.p[0]->nodetype == en_tempref
! 	&& node->v.p[0]->v.p[0]->v.i >= 8
  	&& !(flags & F_USES)) {
  	/* (An)+ */
  	ap1 = (struct amode *) xalloc((int) sizeof(struct amode));
  	ap1->mode = am_ainc;
! 	ap1->preg = node->v.p[0]->v.p[0]->v.i - 8;
! 	return mk_legal(ap1, flags, size);
      }
!     ap1 = g_expr(node->v.p[0], F_AREG | F_IMMED);	/* generate address */
      ap1 = copy_addr(ap1);
      if (ap1->mode == am_areg) {
  	ap1->mode = am_ind;
! 	return mk_legal(ap1, flags, size);
      }
      ap1->mode = am_direct;
!     return mk_legal(ap1, flags, size);
  }
  
  struct amode   *
--- 322,383 ----
  }
  
  struct amode   *
! g_deref(node, type, flags, size)
  /*
   * return the addressing mode of a dereferenced node.
   */
!     struct enode    *node;
!     enum e_bt        type;
!     int              flags; /* determines if ainc modes are acceptable */
!     long             size;
  {
      struct amode   *ap1;
! /*
!  * If a reference to a struct/union is required, return a pointer to the
!  * struct instead
!  */
!     if (type == bt_struct || type == bt_union) {
!         return g_expr(node, F_ALL);
      }
!     if (node->nodetype == en_add) {
! 	return g_index(node);
!     }
!     if (node->nodetype == en_autocon) {
! 	if (node->v.i >= -32768 && node->v.i < 32767) {
  	    ap1 = (struct amode *) xalloc((int) sizeof(struct amode));
  	    ap1->mode = am_indx;
  	    ap1->preg = 6;
! 	    ap1->offset = mk_icon((long) node->v.i);
  	} else {
  	    ap1 = temp_addr();
! 	    g_code(op_move, 4, mk_immed((long) node->v.i), ap1);
  	    g_code(op_add, 4, mk_reg(FRAMEPTR), ap1);
  	    ap1 = copy_addr(ap1);
  	    ap1->mode = am_ind;
  	}
! 	return ap1;
      }
      /* special 68000 instructions */
!     if (node->nodetype == en_ainc
!         && (size ==1 || size ==2 || size ==4)
! 	&& node->v.p[1]->v.i == size
! 	&& node->v.p[0]->nodetype == en_tempref
! 	&& node->v.p[0]->v.i >= 8
  	&& !(flags & F_USES)) {
  	/* (An)+ */
  	ap1 = (struct amode *) xalloc((int) sizeof(struct amode));
  	ap1->mode = am_ainc;
! 	ap1->preg = node->v.p[0]->v.i - 8;
! 	return ap1;
      }
!     ap1 = g_expr(node, F_AREG | F_IMMED);	/* generate address */
      ap1 = copy_addr(ap1);
      if (ap1->mode == am_areg) {
  	ap1->mode = am_ind;
! 	return ap1;
      }
      ap1->mode = am_direct;
!     return ap1;
  }
  
  struct amode   *
***************
*** 385,391 ****
      long            mask;
      int             width = node->bit_width + 1;
  
!     ap = g_deref(node, F_DREG | F_VOL);
      if (node->bit_offset > 0) {
  	if (node->bit_offset <= 8) {
  	    /* can shift with quick constant */
--- 392,399 ----
      long            mask;
      int             width = node->bit_width + 1;
  
!     ap = g_deref(node, node->etype, flags, node->esize);
!     ap = mk_legal(ap, flags, node->esize);
      if (node->bit_offset > 0) {
  	if (node->bit_offset <= 8) {
  	    /* can shift with quick constant */
***************
*** 436,442 ****
  	if (op == op_neg) {
  	    temp_inv();
  	    i = push_param(node->v.p[0]);
! 	    call_library("fpneg");
  	    return func_result(flags, i);
  	}
      }
--- 444,450 ----
  	if (op == op_neg) {
  	    temp_inv();
  	    i = push_param(node->v.p[0]);
! 	    call_library(".fpneg");
  	    return func_result(flags, i);
  	}
      }
***************
*** 477,486 ****
  	i += push_param(node->v.p[0]);
  	switch (op) {
  	  case op_add:
! 	    call_library("fpadd");
  	    break;
  	  case op_sub:
! 	    call_library("fpsub");
  	    break;
  	}
  	return func_result(flags, i);
--- 485,494 ----
  	i += push_param(node->v.p[0]);
  	switch (op) {
  	  case op_add:
! 	    call_library(".fpadd");
  	    break;
  	  case op_sub:
! 	    call_library(".fpsub");
  	    break;
  	}
  	return func_result(flags, i);
***************
*** 602,614 ****
  	i += push_param(node->v.p[0]);
  	switch (node->etype) {
  	  case bt_long:
! 	    call_library("ldiv");
  	    break;
  	  case bt_ulong:
! 	    call_library("uldiv");
  	    break;
            case bt_double:
! 	    call_library("fpdiv");
  	    break;
  	}
  	return func_result(flags, i);
--- 610,622 ----
  	i += push_param(node->v.p[0]);
  	switch (node->etype) {
  	  case bt_long:
! 	    call_library(".ldiv");
  	    break;
  	  case bt_ulong:
! 	    call_library(".uldiv");
  	    break;
            case bt_double:
! 	    call_library(".fpdiv");
  	    break;
  	}
  	return func_result(flags, i);
***************
*** 649,657 ****
  	i = push_param(node->v.p[1]);
  	i += push_param(node->v.p[0]);
  	if (node->etype == bt_long)
! 	    call_library("lrem");
  	else
! 	    call_library("ulrem");
  	return func_result(flags, i);
      }
      fatal("g_mod: illegal type");
--- 657,665 ----
  	i = push_param(node->v.p[1]);
  	i += push_param(node->v.p[0]);
  	if (node->etype == bt_long)
! 	    call_library(".lrem");
  	else
! 	    call_library(".ulrem");
  	return func_result(flags, i);
      }
      fatal("g_mod: illegal type");
***************
*** 701,711 ****
  	i = push_param(node->v.p[1]);
  	i += push_param(node->v.p[0]);
  	if (node->etype == bt_ulong)
! 	    call_library("ulmul");
  	else if (node->etype == bt_double)
! 	    call_library("fpmult");
  	else
! 	    call_library("lmul");
  	return func_result(flags, i);
      }
      fatal("g_mul: illegal type");
--- 709,719 ----
  	i = push_param(node->v.p[1]);
  	i += push_param(node->v.p[0]);
  	if (node->etype == bt_ulong)
! 	    call_library(".ulmul");
  	else if (node->etype == bt_double)
! 	    call_library(".fpmult");
  	else
! 	    call_library(".lmul");
  	return func_result(flags, i);
      }
      fatal("g_mul: illegal type");
***************
*** 723,737 ****
      struct amode   *ap1, *ap2;
      unsigned int    false_label, end_label;
      int		    flagx;
      long size=node->esize;
      false_label = nextlabel++;
      end_label = nextlabel++;
  
!     if (size!=1 && size!=2 && size!=4)
!         fatal("G_HOOK: SIZE PROBLEM");
  
!     flagx = (flags & (F_DREG | F_AREG)) == F_AREG ?
!         F_AREG | F_VOL : F_DREG | F_VOL;
  
      temp_inv(); /* I do not think I can avoid that */
  
--- 731,752 ----
      struct amode   *ap1, *ap2;
      unsigned int    false_label, end_label;
      int		    flagx;
+     int		    result_is_void;
      long size=node->esize;
      false_label = nextlabel++;
      end_label = nextlabel++;
  
!     result_is_void = ( node->etype == bt_void);
!     if (node->etype == bt_struct || node->etype == bt_union) {
!         size = 4;
!     }
  
!     if (!result_is_void) {
!         flagx = (flags & (F_DREG | F_AREG)) == F_AREG ?
!             F_AREG | F_VOL : F_DREG | F_VOL;
!     } else {
!         flagx = F_ALL | F_NOVALUE;
!     }
  
      temp_inv(); /* I do not think I can avoid that */
  
***************
*** 753,759 ****
  
      ap2 = g_expr(node->v.p[1], flagx);
  
!     if (! equal_address(ap1,ap2))
         fatal("G_HOOK: INCONSISTENCY");
  
      g_label(end_label);
--- 768,774 ----
  
      ap2 = g_expr(node->v.p[1], flagx);
  
!     if (!result_is_void && !equal_address(ap1,ap2))
         fatal("G_HOOK: INCONSISTENCY");
  
      g_label(end_label);
***************
*** 790,800 ****
  	g_code(op, (int) node->esize, ap2, ap1);
  	freeop(ap2);
  	return mk_legal(ap1, flags, node->esize);
        case bt_double:
  	if (op == op_add)
! 	    return as_fcall(node, flags, "fpadd");
  	else
! 	    return as_fcall(node, flags, "fpsub");
      }
      fatal("asadd: illegal type");
      /* NOTREACHED */
--- 805,816 ----
  	g_code(op, (int) node->esize, ap2, ap1);
  	freeop(ap2);
  	return mk_legal(ap1, flags, node->esize);
+       case bt_float:
        case bt_double:
  	if (op == op_add)
! 	    return as_fcall(node, flags, ".fpadd", ".asfpadd");
  	else
! 	    return as_fcall(node, flags, ".fpsub", ".asfpsub");
      }
      fatal("asadd: illegal type");
      /* NOTREACHED */
***************
*** 982,993 ****
  	}
  	return mk_legal(ap1, flags, node->esize);
        case bt_long:
! 	return as_fcall(node, flags, "lmul");
        case bt_ulong:
        case bt_pointer:
! 	return as_fcall(node, flags, "ulmul");
        case bt_double:
! 	return as_fcall(node, flags, "fpmult");
      }
      fatal("asmul: illegal type");
      /* NOTREACHED */
--- 998,1010 ----
  	}
  	return mk_legal(ap1, flags, node->esize);
        case bt_long:
! 	return as_fcall(node, flags, ".lmul", ".aslmul");
        case bt_ulong:
        case bt_pointer:
! 	return as_fcall(node, flags, ".ulmul", ".asulmul");
!       case bt_float:
        case bt_double:
! 	return as_fcall(node, flags, ".fpmult",".asfpmult");
      }
      fatal("asmul: illegal type");
      /* NOTREACHED */
***************
*** 1061,1072 ****
  	freeop(ap2);
  	return mk_legal(ap1, flags, 2l);
        case bt_long:
! 	return as_fcall(node, flags, "ldiv");
        case bt_ulong:
        case bt_pointer:
! 	return as_fcall(node, flags, "uldiv");
        case bt_double:
! 	return as_fcall(node, flags, "fpdiv");
      }
      fatal("asdiv: illegal type");
      /* NOTREACHED */
--- 1078,1090 ----
  	freeop(ap2);
  	return mk_legal(ap1, flags, 2l);
        case bt_long:
! 	return as_fcall(node, flags, ".ldiv", ".asldiv");
        case bt_ulong:
        case bt_pointer:
! 	return as_fcall(node, flags, ".uldiv", ".asuldiv");
        case bt_double:
!       case bt_float:
! 	return as_fcall(node, flags, ".fpdiv", ".asfpdiv");
      }
      fatal("asdiv: illegal type");
      /* NOTREACHED */
***************
*** 1104,1113 ****
  	freeop(ap2);
  	return mk_legal(ap1, flags, 2l);
        case bt_long:
! 	return as_fcall(node, flags, "lrem");
        case bt_ulong:
        case bt_pointer:
! 	return as_fcall(node, flags, "ulrem");
      }
      fatal("asmod: illegal type");
      /* NOTREACHED */
--- 1122,1131 ----
  	freeop(ap2);
  	return mk_legal(ap1, flags, 2l);
        case bt_long:
! 	return as_fcall(node, flags, ".lrem", ".aslrem");
        case bt_ulong:
        case bt_pointer:
! 	return as_fcall(node, flags, ".ulrem", ".asulrem");
      }
      fatal("asmod: illegal type");
      /* NOTREACHED */
***************
*** 1183,1207 ****
      else
  	f = F_ALL | F_USES;
      if (node->etype == bt_struct || node->etype == bt_union) {
! 	/* ap1: pointer to structure */
! 	if (lvalue(node->v.p[1]))
! 	    ap1 = g_expr(node->v.p[1]->v.p[0], F_AREG | F_VOL);
! 	else
! 	    /* result of an assignment or of a function call */
! 	    /*
! 	     * we could make this better: at the moment, the result of a
! 	     * function returning a structure is stored in the stack frame of
! 	     * the caller before it is assigned. In the most frequent case
! 	     * (the result is assigned to a structure), g_fcall could pass
! 	     * the appropriate pointer, (this is ap2, to be evaluated soon)
! 	     * but we must make g_fcall know this from here. In the future,
! 	     * this might be implemented, but for now, I suppose that making
! 	     * structure returns efficient is not on top of my priority list.
! 	     */
! 	    ap1 = g_expr(node->v.p[1], F_AREG | F_VOL);
! 
! 	/* ap2: pointer to structer (this node is an L-value) */
! 	ap2 = g_expr(node->v.p[0]->v.p[0], F_AREG | F_VOL);
  	validate(ap1);
  
  	/* hacky: save ap1 if needed later, structassign destroys it */
--- 1201,1212 ----
      else
  	f = F_ALL | F_USES;
      if (node->etype == bt_struct || node->etype == bt_union) {
! /*
!  * Other parts of this module return a pointer to a struct in a register,
!  * not the struct itself
!  */
! 	ap1 = g_expr(node->v.p[1], F_AREG | F_VOL);
! 	ap2 = g_expr(node->v.p[0], F_AREG | F_VOL);
  	validate(ap1);
  
  	/* hacky: save ap1 if needed later, structassign destroys it */
***************
*** 1433,1445 ****
  }
  
  struct amode   *
! as_fcall(node, flags, libname)
      struct enode   *node;
      int             flags;
!     char           *libname;
  /* assignment operations with library calls */
  {
!     char            as_name[25];
      long            i;
      struct amode   *ap1;
      long            size;
--- 1438,1453 ----
  }
  
  struct amode   *
! as_fcall(node, flags, libnam1,libnam2)
      struct enode   *node;
      int             flags;
!     char           *libnam1;
!     char	   *libnam2;
  /* assignment operations with library calls */
  {
! /*
!  * example: libnam1 = ".ldiv", libnam2 = ".asldiv"
!  */
      long            i;
      struct amode   *ap1;
      long            size;
***************
*** 1451,1466 ****
  	ap1 = g_expr(node->v.p[0], F_DREG | F_AREG);
  	g_code(op_move, (int) size, ap1, &push);
  	i += size;
! 	call_library(libname);
  	/* ap1 is always valid and not equal to RESULT */
  	g_code(op_move, (int) size, mk_reg(RESULT), ap1);
      } else {
  	/* pass a pointer to the left side, call special function */
  	i += push_param(node->v.p[0]->v.p[0]);
!         as_name[0]='a'; as_name[1]='s';
! 	strcpy(as_name + 2, libname);
!         /* call_library will do a strsave() */
! 	call_library(as_name);
      }
      g_code(op_add, 4, mk_immed((long) i), mk_reg(STACKPTR));
      if (!(flags & F_NOVALUE)) {
--- 1459,1471 ----
  	ap1 = g_expr(node->v.p[0], F_DREG | F_AREG);
  	g_code(op_move, (int) size, ap1, &push);
  	i += size;
! 	call_library(libnam1);
  	/* ap1 is always valid and not equal to RESULT */
  	g_code(op_move, (int) size, mk_reg(RESULT), ap1);
      } else {
  	/* pass a pointer to the left side, call special function */
  	i += push_param(node->v.p[0]->v.p[0]);
! 	call_library(libnam2);
      }
      g_code(op_add, 4, mk_immed((long) i), mk_reg(STACKPTR));
      if (!(flags & F_NOVALUE)) {
***************
*** 1638,1646 ****
  	    temp_inv();
  	    g_code(op_move, 4, ap, &push);
  	    if (typ2 == bt_long)
! 		call_library("fpftol");
  	    else
! 		call_library("fpftou");
  	    return func_result(flags, 4l);
  	}
          break;
--- 1643,1651 ----
  	    temp_inv();
  	    g_code(op_move, 4, ap, &push);
  	    if (typ2 == bt_long)
! 		call_library(".fpftol");
  	    else
! 		call_library(".fpftou");
  	    return func_result(flags, 4l);
  	}
          break;
***************
*** 1660,1668 ****
  	    temp_inv();
  	    g_code(op_move, 4, ap, &push);
  	    if (typ1 == bt_ulong || typ1 == bt_pointer)
! 		call_library("fputof");
  	    else
! 		call_library("fpltof");
  	    return func_result(flags, 4l);
  	  case bt_float:
            case bt_double:
--- 1665,1673 ----
  	    temp_inv();
  	    g_code(op_move, 4, ap, &push);
  	    if (typ1 == bt_ulong || typ1 == bt_pointer)
! 		call_library(".fputof");
  	    else
! 		call_library(".fpltof");
  	    return func_result(flags, 4l);
  	  case bt_float:
            case bt_double:
***************
*** 1747,1753 ****
  {
      struct amode   *ap1, *ap2;
      unsigned int    lab0, lab1;
!     enum e_bt       typ;
      if (node == 0) {
  	fatal("null node in g_expr");
      }
--- 1752,1759 ----
  {
      struct amode   *ap1, *ap2;
      unsigned int    lab0, lab1;
!     long size;
!     enum e_bt       type;
      if (node == 0) {
  	fatal("null node in g_expr");
      }
***************
*** 1757,1762 ****
--- 1763,1770 ----
  	ap1->offset = node;
  	return mk_legal(ap1, flags, node->esize);
      }
+     type = node->etype;
+     size = node->esize;
      switch (node->nodetype) {
        case en_autocon:
  	ap1 = temp_addr();
***************
*** 1772,1780 ****
  	    ap1 = copy_addr(ap1);
  	    ap1->mode = am_ind;
  	}
! 	return mk_legal(ap1, flags, node->esize);
        case en_ref:
! 	return g_deref(node, flags);
        case en_fieldref:
  	return g_fderef(node, flags);
        case en_tempref:
--- 1780,1795 ----
  	    ap1 = copy_addr(ap1);
  	    ap1->mode = am_ind;
  	}
! 	return mk_legal(ap1, flags, size);
        case en_ref:
! /*
!  * g_deref uses flags and size only to test F_USES
!  */
!         ap1 = g_deref(node->v.p[0], type, flags, node->esize);
!         if (type == bt_struct || type == bt_union)
!             return mk_legal(ap1, flags, 4l);
!         else
! 	    return mk_legal(ap1, flags, size);
        case en_fieldref:
  	return g_fderef(node, flags);
        case en_tempref:
***************
*** 1786,1792 ****
  	    ap1->mode = am_areg;
  	    ap1->preg = node->v.i - 8;
  	}
! 	return mk_legal(ap1, flags, node->esize);
        case en_uminus:
  	return g_unary(node, flags, op_neg);
        case en_compl:
--- 1801,1807 ----
  	    ap1->mode = am_areg;
  	    ap1->preg = node->v.i - 8;
  	}
! 	return mk_legal(ap1, flags, size);
        case en_uminus:
  	return g_unary(node, flags, op_neg);
        case en_compl:
***************
*** 1807,1814 ****
  	 * 68000 mulu, muls instructions. ugly, but it gives a big
  	 * performance increase
  	 */
! 	typ=node->etype;
! 	if (typ == bt_long || typ == bt_ulong || typ == bt_pointer) {
  	    if (tst_ushort(node->v.p[0]) && tst_ushort(node->v.p[1])) {
  		node->v.p[0]->etype = bt_ushort;
  		node->v.p[0]->esize = 2;
--- 1822,1828 ----
  	 * 68000 mulu, muls instructions. ugly, but it gives a big
  	 * performance increase
  	 */
! 	if (type == bt_long || type == bt_ulong || type == bt_pointer) {
  	    if (tst_ushort(node->v.p[0]) && tst_ushort(node->v.p[1])) {
  		node->v.p[0]->etype = bt_ushort;
  		node->v.p[0]->esize = 2;
***************
*** 1831,1838 ****
        case en_lsh:
  	return g_shift(node, flags, op_asl);
        case en_rsh:
!         typ=node->etype;
!         if (typ==bt_ulong || typ==bt_ushort || typ==bt_uchar)
  	    return g_shift(node, flags, op_lsr);
  	else
  	    return g_shift(node, flags, op_asr);
--- 1845,1851 ----
        case en_lsh:
  	return g_shift(node, flags, op_asl);
        case en_rsh:
!         if (type==bt_ulong || type==bt_ushort || type==bt_uchar)
  	    return g_shift(node, flags, op_lsr);
  	else
  	    return g_shift(node, flags, op_asr);
***************
*** 1847,1854 ****
        case en_aslsh:
  	return g_asshift(node, flags, op_asl);
        case en_asrsh:
!         typ=node->etype;
!         if (typ==bt_ulong || typ==bt_ushort || typ==bt_uchar)
  	    return g_asshift(node, flags, op_lsr);
  	else
  	    return g_asshift(node, flags, op_asr);
--- 1860,1866 ----
        case en_aslsh:
  	return g_asshift(node, flags, op_asl);
        case en_asrsh:
!         if (type==bt_ulong || type==bt_ushort || type==bt_uchar)
  	    return g_asshift(node, flags, op_lsr);
  	else
  	    return g_asshift(node, flags, op_asr);
***************
*** 1884,1890 ****
  	g_label(lab0);
  	g_code(op_moveq, 0, mk_immed(0l), ap1);
  	g_label(lab1);
! 	return mk_legal(ap1, flags, node->esize);
        case en_cond:
  	return g_hook(node, flags);
        case en_void:
--- 1896,1902 ----
  	g_label(lab0);
  	g_code(op_moveq, 0, mk_immed(0l), ap1);
  	g_label(lab1);
! 	return mk_legal(ap1, flags, size);
        case en_cond:
  	return g_hook(node, flags);
        case en_void:
***************
*** 1893,1898 ****
--- 1905,1922 ----
        case en_fcall:
  	return g_fcall(node, flags);
        case en_cast:
+         /*
+          * On the 68000, suppress all casts between any of
+          * long, unsigned long, pointer
+          */
+         if (type == bt_pointer || type == bt_long || type == bt_ulong) {
+             type = node->v.p[0]->etype;
+             if (type == bt_pointer || type == bt_long || type == bt_ulong)
+                 return g_expr(node->v.p[0], flags);
+         }
+         /*
+          * The cast really results in some work
+          */
  	return g_cast(g_expr(node->v.p[0], F_ALL | F_USES),
  		      node->v.p[0]->etype,
  		      node->etype, flags);
***************
*** 2021,2027 ****
  	temp_inv();
  	i = push_param(node->v.p[1]);
  	i += push_param(node->v.p[0]);
! 	call_library("fpcmp");
  	g_code(op_add, 4, mk_immed((long) i), mk_reg(STACKPTR));
  	return 0;
      }
--- 2045,2051 ----
  	temp_inv();
  	i = push_param(node->v.p[1]);
  	i += push_param(node->v.p[0]);
! 	call_library(".fpcmp");
  	g_code(op_add, 4, mk_immed((long) i), mk_reg(STACKPTR));
  	return 0;
      }
***************
*** 2093,2099 ****
  	    long            i;
  	    temp_inv();
  	    i = push_param(node);
! 	    call_library("fptst");
  	    /* The pop-off does not change the condition codes */
  	    g_code(op_add, 4, mk_immed((long) i), mk_reg(STACKPTR));
  	} else {
--- 2117,2123 ----
  	    long            i;
  	    temp_inv();
  	    i = push_param(node);
! 	    call_library(".fptst");
  	    /* The pop-off does not change the condition codes */
  	    g_code(op_add, 4, mk_immed((long) i), mk_reg(STACKPTR));
  	} else {
***************
*** 2171,2177 ****
  	    long            i;
  	    temp_inv();
  	    i = push_param(node);
! 	    call_library("fptst");
  	    /* The pop-off does not change the condition codes */
  	    g_code(op_add, 4, mk_immed((long) i), mk_reg(STACKPTR));
  	} else {
--- 2195,2201 ----
  	    long            i;
  	    temp_inv();
  	    i = push_param(node);
! 	    call_library(".fptst");
  	    /* The pop-off does not change the condition codes */
  	    g_code(op_add, 4, mk_immed((long) i), mk_reg(STACKPTR));
  	} else {
diff -c c68III/genstmt.c c68III.1/genstmt.c
*** c68III/genstmt.c	Mon Feb  4 19:58:33 1991
--- c68III.1/genstmt.c	Fri Mar  1 10:49:57 1991
***************
*** 357,362 ****
--- 357,363 ----
      struct amode   *ap, *ap1, *ap2;
      struct enode   *ep;
      long            size;
+     enum e_bt	    type;
      long            min_caselabel, max_caselabel, nxt_caselabel;
      int             number_of_cases;
      defcase = 0;
***************
*** 374,379 ****
--- 375,381 ----
      ap = g_expr(stmt->exp, F_REG);
  #endif
      size = stmt->exp->esize;
+     type = stmt->exp->etype;
      stmt = stmt->s1;
      /*
       * analyze the switch statement
***************
*** 407,422 ****
  	 * we need the case label as a 32-bit item.
  	 */
  #ifdef MC680X0
! 	if (size == 1)
! 	    g_code(op_and, 4, mk_immed((long) 255), ap);
! 	else if (size == 2)
! 	    g_code(op_and, 4, mk_immed((long) 65535), ap);
  #endif
  #ifdef INTEL_386
!         if (size == 1)
!             g_code (op_movzbl, 0, ap, ap);
!         else if (size == 2)
!             g_code (op_movzwl, 0, ap, ap);
  #endif
  	/*
  	 * move the interval
--- 409,442 ----
  	 * we need the case label as a 32-bit item.
  	 */
  #ifdef MC680X0
!         switch (type) {
!           case bt_char:
!             g_code(op_ext, 2, ap, NIL_AMODE);
!             /*FALLTHROUGH*/
!           case bt_short:
!             g_code(op_ext, 4, ap, NIL_AMODE);
!             break;
!           case bt_uchar:
!             g_code(op_and, 4, mk_immed(255l), ap);
!             break;
!           case bt_ushort:
!             g_code(op_and, 4, mk_immed(65535l), ap);
!         }
  #endif
  #ifdef INTEL_386
!         switch (type) {
!           case bt_char:
!             g_code(op_movsbl, 0, ap, ap);
!             break;
!           case bt_short:
!             g_code(op_movswl, 0, ap, ap);
!             break;
!           case bt_uchar:
!             g_code(op_movzbl, 0, ap, ap);
!             break;
!           case bt_ushort:
!             g_code(op_movzwl, 0, ap, ap);
!         }
  #endif
  	/*
  	 * move the interval
***************
*** 686,691 ****
--- 706,712 ----
  #ifdef INTEL_386
              /* return floating point value on top of fpu stack */
              (void) g_expr(stmt->exp, F_FPSTACK);
+             /* DO NOT call freeop since this might pop the value off */
              break;
  #endif
  #ifdef MC68000
***************
*** 751,756 ****
--- 772,780 ----
  	g_code(op_rts, 0, NIL_AMODE, NIL_AMODE);
  #endif
  #ifdef INTEL_386
+         /*
+          * Adjust stack pointer to initial value
+          */
          if (regs_used > 0 && !is_leaf_function) {
              stack_offset = lc_auto + 4*regs_used;
              ap = mk_reg(EBP);
***************
*** 771,781 ****
          g_code(op_ret, 0, NIL_AMODE, NIL_AMODE);
  #endif
  #ifdef ICODE
! 	if (icode_option) {
! 	    if (save_mask != 0)
! 		fprintf(icode, "\t$regpop %04x\n", save_mask);
  	    fprintf(icode, "\t$leave\n");
- 	}
  #endif
      } else {
  	g_code(op_bra, 0, mk_label(retlab), NIL_AMODE);
--- 795,802 ----
          g_code(op_ret, 0, NIL_AMODE, NIL_AMODE);
  #endif
  #ifdef ICODE
! 	if (icode_option)
  	    fprintf(icode, "\t$leave\n");
  #endif
      } else {
  	g_code(op_bra, 0, mk_label(retlab), NIL_AMODE);
***************
*** 886,892 ****
      if (lc_auto < 32768l)
  	g_code(op_link, 0, mk_reg(FRAMEPTR), mk_immed((long) -lc_auto));
      else {
! 	g_code(op_link, 0, mk_reg(FRAMEPTR), mk_immed((long) 0));
  	g_code(op_sub, 4, mk_immed(lc_auto), mk_reg(STACKPTR));
      }
  #endif
--- 907,913 ----
      if (lc_auto < 32768l)
  	g_code(op_link, 0, mk_reg(FRAMEPTR), mk_immed((long) -lc_auto));
      else {
! 	g_code(op_link, 0, mk_reg(FRAMEPTR), mk_immed(0l));
  	g_code(op_sub, 4, mk_immed(lc_auto), mk_reg(STACKPTR));
      }
  #endif
diff -c c68III/getsym.c c68III.1/getsym.c
*** c68III/getsym.c	Mon Feb  4 19:58:34 1991
--- c68III.1/getsym.c	Fri Mar  1 10:49:58 1991
***************
*** 29,35 ****
  
  #include <ctype.h>
  
! static int      err_num[80];
  static int      numerrs;
  static char     linein[500];
  static char    *lptr;
--- 29,36 ----
  
  #include <ctype.h>
  
! #define MAX_NUM_ERRS 80
! static int      err_num[MAX_NUM_ERRS];
  static int      numerrs;
  static char     linein[500];
  static char    *lptr;
***************
*** 43,48 ****
--- 44,52 ----
  isalnum(c)
      char            c;
  {
+ /*
+  * This function makes assumptions about the character codes.
+  */
      return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
  	(c >= '0' && c <= '9');
  }
***************
*** 74,79 ****
--- 78,86 ----
  isdigit(c)
      char            c;
  {
+ /*
+  * This function makes assumptions about the character codes.
+  */
      return (c >= '0' && c <= '9');
  }
  
***************
*** 150,156 ****
  	    getsym();
  	if (lastst != iconst)
  	    error(ERR_PREPROC);
! 	act_line = ival;
  	/* scan file name */
  	i = 0;
  	while (isspace(*lptr))
--- 157,163 ----
  	    getsym();
  	if (lastst != iconst)
  	    error(ERR_PREPROC);
! 	act_line = ival-1;
  	/* scan file name */
  	i = 0;
  	while (isspace(*lptr))
***************
*** 188,197 ****
  error(n)
      int             n;
  {
!     err_num[numerrs++] = n;
      ++total_errors;
      fprintf(stderr, "\"%s\", line %d: error %d: %s\n",
  	    act_file, act_line, n, __err[n]);
  }
  
  void do_warning()
--- 195,214 ----
  error(n)
      int             n;
  {
!     if (numerrs < MAX_NUM_ERRS)
!         err_num[numerrs++] = n;
      ++total_errors;
      fprintf(stderr, "\"%s\", line %d: error %d: %s\n",
  	    act_file, act_line, n, __err[n]);
+ /*
+  * Do not proceed if more than MAX_ERROR_COUNT errors were detected.
+  * MAX_ERROR_COUNT should be high since each error might be reported
+  * more than once
+  */
+     if (total_errors > MAX_ERROR_COUNT) {
+         fprintf(stderr, "\n\nProgram terminated due to maximum error count\n");
+         exit(1);
+     }
  }
  
  void do_warning()
***************
*** 234,245 ****
   *
   * this routine handles all of the escape mechanisms for characters in strings
   * and character constants.
   */
  int
! getsch()
  {				/* return an in-quote character */
      register int    i, j;
!     if (lastch == '\n')
  	return -1;
      if (lastch != '\\') {
  	i = lastch;
--- 251,268 ----
   *
   * this routine handles all of the escape mechanisms for characters in strings
   * and character constants.
+  * flag is 0, if a character constant is being scanned,
+  * flag is 1, if a string constant is being scanned
   */
  int
! getsch(flag)
!     int flag;
  {				/* return an in-quote character */
      register int    i, j;
! /*
!  * if we scan a string constant, stop if '"' is seen
!  */
!     if (lastch == '\n' || (flag && lastch == '"'))
  	return -1;
      if (lastch != '\\') {
  	i = lastch;
***************
*** 250,257 ****
      if (isdigit(lastch)) {
  	i = 0;
  	for (j = 0; j < 3; ++j) {
! 	    if (lastch <= '7' && lastch >= '0')
! 		i = (i << 3) + lastch - '0';
  	    else
  		break;
  	    getch();
--- 273,280 ----
      if (isdigit(lastch)) {
  	i = 0;
  	for (j = 0; j < 3; ++j) {
! 	    if (isdigit(lastch) && lastch <= '7')
! 		i = 8*i + radix36(lastch);
  	    else
  		break;
  	    getch();
***************
*** 264,270 ****
      getch();
      switch (i) {
        case '\n':
! 	return getsch();
        case 'b':
  	return '\b';
        case 'f':
--- 287,293 ----
      getch();
      switch (i) {
        case '\n':
! 	return getsch(1);
        case 'b':
  	return '\b';
        case 'f':
***************
*** 275,280 ****
--- 298,307 ----
  	return '\r';
        case 't':
  	return '\t';
+       case 'a':
+ 	return '\a';
+       case 'v':
+ 	return '\v';
        default:
  	return i;
      }
***************
*** 284,289 ****
--- 311,319 ----
  radix36(c)
      char            c;
  {
+ /*
+  * This function makes assumptions about the character codes.
+  */
      if (isdigit(c))
  	return c - '0';
      if (c >= 'a' && c <= 'z')
***************
*** 349,356 ****
      r = 0.0;
  #endif
      if (b == 10) {
! 	while ('0' <= lastch && lastch <= '9') {
! 	    j = lastch - '0';
  	    i = 8 * i + 2 * i + j;
  #ifndef NOFLOAT
  	    r = 10.0 * r + (double) j;
--- 379,386 ----
      r = 0.0;
  #endif
      if (b == 10) {
! 	while (isdigit(lastch)) {
! 	    j = radix36(lastch);
  	    i = 8 * i + 2 * i + j;
  #ifndef NOFLOAT
  	    r = 10.0 * r + (double) j;
***************
*** 383,389 ****
      double          frmul;
      frmul = 0.1;
      while (isdigit(lastch)) {
! 	rval += frmul * (lastch - '0');
  	getch();
  	frmul *= 0.1;
      }
--- 413,419 ----
      double          frmul;
      frmul = 0.1;
      while (isdigit(lastch)) {
! 	rval += frmul * radix36(lastch);
  	getch();
  	frmul *= 0.1;
      }
***************
*** 409,419 ****
  	exmul = 10.0;
      getbase(10);
      lastst = rconst;
!     if (ival > 255)
! 	error(ERR_FPCON);
!     else
! 	while (ival--)
! 	    expo *= exmul;
      rval = expo;
  #endif
  }
--- 439,446 ----
  	exmul = 10.0;
      getbase(10);
      lastst = rconst;
!     while (ival--)
!         expo *= exmul;
      rval = expo;
  #endif
  }
***************
*** 452,459 ****
--- 479,496 ----
  	getch();
  	getexp();		/* get the exponent */
      }
+     /*
+      * look for l and u qualifiers
+      */
      if (lastst == iconst)
  	test_int(0);
+     /*
+      * look for (but ignore) f and l qualifiers
+      */
+     if (lastst == rconst)
+         if (lastch == 'f' || lastch == 'F' || lastch == 'l' ||
+             lastch == 'L')
+             getch();
  }
  
  /*
***************
*** 596,602 ****
  	    break;
  	  case '\'':
  	    getch();
! 	    ival = getsch();	/* get a string char */
  	    if (lastch != '\'')
  		error(ERR_SYNTAX);
  	    else
--- 633,639 ----
  	    break;
  	  case '\'':
  	    getch();
! 	    ival = getsch(0);	/* get a string char */
  	    if (lastch != '\'')
  		error(ERR_SYNTAX);
  	    else
***************
*** 605,621 ****
  	    break;
  	  case '\"':
  	    getch();
! 	    for (i = 0; i < MAX_STRLEN; ++i) {
! 		if (lastch == '\"')
  		    break;
! 		if ((j = getsch()) == -1)
! 		    break;
! 		else
  		    laststr[i] = j;
  	    }
  	    /*
  	     * Attention: laststr may contain zeroes!
  	     */
  	    lstrlen = i;
  	    laststr[i] = 0;
  	    lastst = sconst;
--- 642,661 ----
  	    break;
  	  case '\"':
  	    getch();
! 	    for (i = 0; ; ++i) {
! 		if ((j = getsch(1)) == -1)
  		    break;
!                 if (i < MAX_STRLEN)
  		    laststr[i] = j;
  	    }
  	    /*
  	     * Attention: laststr may contain zeroes!
  	     */
+             if (i > MAX_STRLEN) {
+                 i = MAX_STRLEN;
+                 do_warning();
+                 fprintf(stderr,"Too long string constant was cut\n");
+             }
  	    lstrlen = i;
  	    laststr[i] = 0;
  	    lastst = sconst;
diff -c c68III/init.c c68III.1/init.c
*** c68III/init.c	Mon Feb  4 19:58:35 1991
--- c68III.1/init.c	Fri Mar  1 10:49:59 1991
***************
*** 28,35 ****
  #include	"cglbdec.h"
  
  static long     inittype(), initstruct(), initarray();
! static          initchar(), initshort(), initlong(), initfloat(), initpointer();
! static		initdouble();
  
  doinit(sp, align)
      struct sym     *sp;
--- 28,36 ----
  #include	"cglbdec.h"
  
  static long     inittype(), initstruct(), initarray();
! static int      initchar(), initshort(), initlong(), initfloat(), initpointer();
! static int	initdouble();
! static struct enode *constexpr();
  
  doinit(sp, align)
      struct sym     *sp;
***************
*** 168,174 ****
      return tp->size;
  }
  
! static
  initchar()
  {
      genbyte((int) intexpr());
--- 169,175 ----
      return tp->size;
  }
  
! static int
  initchar()
  {
      genbyte((int) intexpr());
***************
*** 175,181 ****
      return 1;
  }
  
! static
  initshort()
  {
      genword((int) intexpr());
--- 176,182 ----
      return 1;
  }
  
! static int
  initshort()
  {
      genword((int) intexpr());
***************
*** 182,195 ****
      return 2;
  }
  
! static
  initlong()
  {
!     genlong(intexpr());
      return 4;
  }
  
! static
  initfloat()
  {
  #ifndef NOFLOAT
--- 183,207 ----
      return 2;
  }
  
! static int
  initlong()
  {
! /*
!  * We allow longs to be initialized with pointers now.
!  * Thus, we call constexpr() instead of intexpr.
!  */
! #if 0
! /*
!  * This is more strict
!  */
!     genlong(intexp());
      return 4;
+ #endif
+     genptr(constexpr());
+     return 4;
  }
  
! static int
  initfloat()
  {
  #ifndef NOFLOAT
***************
*** 202,208 ****
      return 4;
  }
  
! static
  initdouble()
  {
  #ifdef NOFLOAT
--- 214,220 ----
      return 4;
  }
  
! static int
  initdouble()
  {
  #ifdef NOFLOAT
***************
*** 217,236 ****
      return tp_double.size;
  }
  
! static
  initpointer()
  {
!     struct enode   *ep;
!     TYP            *tp;
!     tp = exprnc(&ep);
!     if (tp == 0)
  	error(ERR_SYNTAX);
!     else {
! 	opt4(&ep);
! 	if (tst_const(ep))
! 	    genptr(ep);
! 	else
! 	    error(ERR_ILLINIT);
      }
!     return 4;
  }
--- 229,255 ----
      return tp_double.size;
  }
  
! static int
  initpointer()
  {
!     genptr(constexpr());
!     return 4;
! }
! 
! static struct enode *
! constexpr()
! {
!     struct enode *ep;
!     struct typ   *tp;
!     tp=exprnc(&ep);
!     if (tp == 0) {
!         error(ERR_SYNTAX);
!         return 0;
!     }
!     opt4(&ep);
!     if (!tst_const(ep)) {
  	error(ERR_SYNTAX);
! 	return 0;
      }
!     return ep;
  }
