[gnu.gcc.bug] long long support for Mips

loepere@WOMBAT.WESTFORD.CCUR.COM (09/19/89)

I believe that the following set of changes corrects support for "long
long" on Mips.  (By the way, when building gnulib2, the Makefile line
invoking gcc should name ./gcc.) These changes are for gcc-1.35.98. -
Keith

- New definition of movdi (I should do some combination with logic in
movsi some day):

(define_insn "movdi"
  [(set (match_operand:DI 0 "general_operand" "=r,*r,*m,*r,*r")
	(match_operand:DI 1 "general_operand" "r,*m,*r,J,i"))]
  ""
  "*
{
  extern rtx adj_offsettable_operand ();

  switch (which_alternative)
    {
    case 0:
      {
	rtx xops[2];
	if (REGNO (operands[0]) != (REGNO (operands[1]) +1))
	  {
	    /* TAKE CARE OF OVERLAPS */
	    xops[0] =  gen_rtx (REG, SImode, REGNO (operands[0]));
	    xops[1] =  gen_rtx (REG, SImode, REGNO (operands[1]));
	    output_asm_insn (\"add%:\\t%0,$0,%1\\t#movdi %1 -> %0\", xops);
	    xops[0] =  gen_rtx (REG, SImode, REGNO (xops[0])+1);
	    xops[1] =  gen_rtx (REG, SImode, REGNO (xops[1])+1);
	    output_asm_insn (\"add%:\\t%0,$0,%1\\t#movdi %1 -> %0\", xops);
	  }
	else
	  {
	    /* TAKE CARE OF OVERLAPS */
	    xops[0] =  gen_rtx (REG, SImode, REGNO (operands[0])+1);
	    xops[1] =  gen_rtx (REG, SImode, REGNO (operands[1])+1);
	    output_asm_insn (\"add%:\\t%0,$0,%1\\t#movdi %1 -> %0\", xops);
	    xops[0] =  gen_rtx (REG, SImode, REGNO (xops[0])-1);
	    xops[1] =  gen_rtx (REG, SImode, REGNO (xops[1])-1);
	    output_asm_insn (\"add%:\\t%0,$0,%1\\t#movdi %1 -> %0\", xops);
	  }
	break;
      }
    case 1:
      {
	/* No overlap here */
	rtx xops[2];
	xops[0] =  gen_rtx (REG, SImode, REGNO (operands[0]));
	if (GET_CODE (operands[1]) == MEM)
	  xops[1] =  gen_rtx (MEM, SImode, XEXP (operands[1], 0));
	else abort ();
	output_asm_insn (\"lw\\t%0,%1\\t#movdi %1 (mem) -> %0\", xops);
	xops[0] =  gen_rtx (REG, SImode, REGNO (operands[0])+1);
	xops[1] =  adj_offsettable_operand (xops[1], 4);
	output_asm_insn (\"lw\\t%0,%1\\t#movdi %1(mem) -> %0\", xops);
	break;
      }
    case 2:
      {
	/* No overlap here */
	rtx xops[2];
	xops[1] =  gen_rtx (REG, SImode, REGNO (operands[1]));
	if (GET_CODE (operands[0]) == MEM)
	  xops[0] =  gen_rtx (MEM, SImode, XEXP (operands[0], 0));
	else abort ();
	output_asm_insn (\"sw\\t%1,%0\\t#movdi %1 -> %0(mem)\", xops);
	xops[1] =  gen_rtx (REG, SImode, REGNO (operands[1])+1);
	xops[0] =  adj_offsettable_operand (xops[0], 4);
	output_asm_insn (\"sw\\t%1,%0\\t#movdi %1 -> %0 (mem)\", xops);
	break;
      }
    case 3:
      {
	/* No overlap here */
	rtx xops[1];
	xops[0] =  gen_rtx (REG, SImode, REGNO (operands[0]));
	output_asm_insn (\"add%:\\t%0,$0,$0\\t#movdi\\t0 -> %0\", xops);
	xops[0] =  gen_rtx (REG, SImode, REGNO (operands[0])+1);
	output_asm_insn (\"add%:\\t%0,$0,$0\\t#movdi\\t0 -> %0\", xops);
	break;
      }
    case 4:
      {
	/* No overlap here */
	rtx xops[3];
	switch (GET_CODE (operands[1]))
	  {
	  case CONST_INT:
	  case CONST_DOUBLE:
	    {
	      int values[2];
	      short half;
	      if (GET_CODE (operands[1]) == CONST_INT)
		{
		  values[0] = 0;
		  values[1] = INTVAL (operands[1]);
		}
	      else
		{
		  values[0] = CONST_DOUBLE_HIGH (operands[1]);
		  values[1] = CONST_DOUBLE_LOW (operands[1]);
		}
	      for (half = 0; half <= 1; half++)
		{
		  xops[0] =  gen_rtx (REG, SImode, REGNO (operands[0]) + half);
		  if (values[half] == 0)
		    output_asm_insn (\"add%:\\t%0,$0,$0\\t#movdi\\t0 -> %0\", xops);
		  else
		    {
		      xops[2] = gen_rtx (CONST_INT, VOIDmode, values[half]);
		      if ((values[half] >> 16)
			  && (values[half] & 0xffff))
			{
			  if (!((-values[half]) >> 16))
			    {
			      xops[1] = gen_rtx (CONST_INT, VOIDmode,
						 values[half] & 0xffff);
			      output_asm_insn (\"addi%:\\t%0,$0,%x1\\t#movdi low part of %2\",
					       xops);
			    }
			  else
			    {
			      xops[1] = gen_rtx (CONST_INT, VOIDmode,
						 values[half]>>16);
			      output_asm_insn (\"lui\\t%0,%x1\\t#movdi high part of %2\", xops);
			      xops[1] = gen_rtx (CONST_INT, VOIDmode,
						 values[half] & 0xffff);
			      output_asm_insn (\"ori\\t%0,%x1\\t#movdi low part of %2\", xops);
			    }
			}
		      else if  (values[half] >> 16)
			{
			  xops[1] = gen_rtx (CONST_INT, VOIDmode,
					     values[half]>>16);
			  output_asm_insn (\"lui\\t%0,%x1\\t#movdi high part of %2\", xops);
			}
		      else
			{
			  xops[1] = gen_rtx (CONST_INT, VOIDmode,
					     values[half] & 0xffff);
			  output_asm_insn (\"ori\\t%0,$0,%x1\\t#movdi low part of %2\",
					   xops);
			}
		    }
		}
	      break;
	    }
	  case SYMBOL_REF:
	  case LABEL_REF:
	  case CONST:
	    {
	      xops[0] =  gen_rtx (REG, SImode, REGNO (operands[0]));
	      output_asm_insn (\"add%:\\t%0,$0,$0\\t#movdi\\t0 -> %0\", xops);
	      xops[0] =  gen_rtx (REG, SImode, REGNO (operands[0])+1);
	      xops[1] = operands[1];
	      output_asm_insn (\"la\\t%0,%a1\\t#movdi %a1 -> %0\", xops);
	      break;
	    }
	  default:
	    abort ();
	  }
	break;
      }
    }
  return \"\";
}")

- Also, remove the extra assignment to xops[1] toward the end of movsi:

  			     (INTVAL (operands[1]))>>16);
  	  output_asm_insn (\"lui\\t%0,%x1\\t#movsi high part of %2\", xops);
- 	  xops[1] = gen_rtx (CONST_INT, VOIDmode,
- 			     (INTVAL (operands[1])) & 0xffff);
  	}
        else

- Diffs to out-mips.c:

***************
*** 133,138
  static struct
  {
!   enum arg_state nxs_if_f, nxs_if_g;
!   short reg_if_f, reg_if_g;
  }
    arg_state_table[(int) (ARG_STA_GGGG + 1)]  = ARG_STA_AUTOMA;

--- 133,138 -----
  static struct
  {
!   enum arg_state nxs_if_f, nxs_if_g, nxs_if_d;
!   short reg_if_f, reg_if_g, reg_if_d;
  }
    arg_state_table[(int) (ARG_STA_DD + 1)]  = ARG_STA_AUTOMA;
***************
*** 136,140
    short reg_if_f, reg_if_g;
  }
!   arg_state_table[(int) (ARG_STA_GGGG + 1)]  = ARG_STA_AUTOMA;
  
  

--- 136,140 -----
    short reg_if_f, reg_if_g, reg_if_d;
  }
!   arg_state_table[(int) (ARG_STA_DD + 1)]  = ARG_STA_AUTOMA;
  
  
***************
*** 154,158
      = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
         ? arg_state_table[(int)((cum->arg_rec_state))].nxs_if_f
!        : arg_state_table[(int)((cum->arg_rec_state))].nxs_if_g);
  
    (cum->arg_num)++;

--- 154,160 -----
      = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
         ? arg_state_table[(int)((cum->arg_rec_state))].nxs_if_f
!        : ((mode == DImode)
! 	  ? arg_state_table[(int)((cum->arg_rec_state))].nxs_if_d
! 	  : arg_state_table[(int)((cum->arg_rec_state))].nxs_if_g));
  
    (cum->arg_num)++;
***************
*** 171,175
      = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
         ? arg_state_table[(int)((cum->arg_rec_state))].reg_if_f
!        : arg_state_table[(int)((cum->arg_rec_state))].reg_if_g);
  
    if (mode == BLKmode)

--- 173,179 -----
      = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
         ? arg_state_table[(int)((cum->arg_rec_state))].reg_if_f
!        : ((mode == DImode)
! 	  ? arg_state_table[(int)((cum->arg_rec_state))].reg_if_d
! 	  : arg_state_table[(int)((cum->arg_rec_state))].reg_if_g));
  
    if (mode == BLKmode)

- Diffs to tm-mips.h:

***************
*** 680,716
  				/* 's book page D-22 */
  
! #define CUMULATIVE_ARGS struct    { enum arg_state arg_rec_state;int restype,arg_num;}
  
  enum arg_state     { ARG_STA_INIT =0,
  		     ARG_STA_F    =1, /* $f12 */
  		     ARG_STA_FF   =2, /* $f12 $f14 */
  		     ARG_STA_FG   =3, /* $f12 $6   */
! 		     ARG_STA_FGG  =4, /* $f12 $6 $7 */
! 		     ARG_STA_FGF  =5, /* $f12 $6 STACK */
! 		     ARG_STA_G    =6, /* $4 */
! 		     ARG_STA_GF   =7, /* $4  ($6,$7) */
! 		     ARG_STA_GG   =8, /* $4 $5 */
! 		     ARG_STA_GGF  =9, /* $4 $5 ($6,$7) */
! 		     ARG_STA_GGG  =10,/* $4 $5 $6 */
! 		     ARG_STA_GGGF =11,/* $4 $5 $6 STACK */
! 		     ARG_STA_GGGG =12 /* $4 $5 $6 $7 */
  		     };
  #define ARG_STA_AUTOMA							\
  {									\
!   {ARG_STA_F,ARG_STA_G,44,4        },   /* ARG_STA_INIT */		\
!   {ARG_STA_FF,ARG_STA_FG,46,6      },   /* ARG_STA_F    */		\
!   {ARG_STA_FF,ARG_STA_FF,-1,-1     },   /* ARG_STA_FF   */		\
!   {ARG_STA_FGF,ARG_STA_FGG,-1,7    },   /* ARG_STA_FG   */		\
!   {ARG_STA_FGG,ARG_STA_FGG,-1,-1   },   /* ARG_STA_FGG  */		\
!   {ARG_STA_FGF,ARG_STA_FGF,-1,-1   },   /* ARG_STA_FGF  */		\
!   {ARG_STA_GF,ARG_STA_GG,-2,5      },   /* ARG_STA_G    */		\
!   {ARG_STA_GF,ARG_STA_GF,-1,-1     },   /* ARG_STA_GF   */		\
!   {ARG_STA_GGF,ARG_STA_GGG,-2,6    },   /* ARG_STA_GG   */		\
!   {ARG_STA_GGF,ARG_STA_GGF,-1,-1   },   /* ARG_STA_GGF  */		\
!   {ARG_STA_GGGF,ARG_STA_GGGG,-1,7  },   /* ARG_STA_GGG  */		\
!   {ARG_STA_GGGF,ARG_STA_GGGF,-1,-1 },   /* ARG_STA_GGGF */		\
!   {ARG_STA_GGGG,ARG_STA_GGGG,-1,-1 }    /* ARG_STA_GGGG */		\
  }
  
  /* Initialize a variable CUM of type CUMULATIVE_ARGS
     for a call to a function whose data type is FNTYPE.

--- 680,746 -----
  				/* 's book page D-22 */
  
! #define CUMULATIVE_ARGS cumulative_args_t
  
+ /* F means that a floating point (single or double) value was encountered;
+    G means a general value (<= 32 bits) and D means a long long (double) value. */
+ 
  enum arg_state     { ARG_STA_INIT =0,
  		     ARG_STA_F    =1, /* $f12 */
  		     ARG_STA_FF   =2, /* $f12 $f14 */
  		     ARG_STA_FG   =3, /* $f12 $6   */
! 		     ARG_STA_FGF  =4, /* $f12 $6 STACK */
! 		     ARG_STA_FGG  =5, /* $f12 $6 $7 */
! 		     ARG_STA_FGD  =6, /* $f12 $6 STACK */
! 		     ARG_STA_FD   =7, /* $f12 ($6,$7) */
! 		     ARG_STA_G    =8, /* $4 */
! 		     ARG_STA_GF   =9, /* $4  ($6,$7) */
! 		     ARG_STA_GG   =10,/* $4 $5 */
! 		     ARG_STA_GGF  =11,/* $4 $5 ($6,$7) */
! 		     ARG_STA_GGG  =12,/* $4 $5 $6 */
! 		     ARG_STA_GGGF =13,/* $4 $5 $6 STACK */
! 		     ARG_STA_GGGG =14,/* $4 $5 $6 $7 */
! 		     ARG_STA_GGGD =15,/* $4 $5 $6 STACK */
! 		     ARG_STA_GGD  =16,/* $4 $5 ($6,$7) */
! 		     ARG_STA_GD   =17,/* $4 ($6,$7) */
! 		     ARG_STA_D    =18,/* ($4,$5) */
! 		     ARG_STA_DF   =19,/* ($4,$5) ($6,$7) */
! 		     ARG_STA_DG   =20,/* ($4,$5) $6 */
! 		     ARG_STA_DGF  =21,/* ($4,$5) $6 STACK */
! 		     ARG_STA_DGG  =22,/* ($4,$5) $6 $7 */
! 		     ARG_STA_DGD  =23,/* ($4,$5) $6 STACK */
! 		     ARG_STA_DD   =24 /* ($4,$5) ($6,$7) */
  		     };
+ 
  #define ARG_STA_AUTOMA							\
  {									\
!   {ARG_STA_F,ARG_STA_G,ARG_STA_D,44,4,4},	/* ARG_STA_INIT */	\
!   {ARG_STA_FF,ARG_STA_FG,ARG_STA_FD,46,6,6},	/* ARG_STA_F */		\
!   {ARG_STA_FF,ARG_STA_FF,ARG_STA_FF,-1,-1,-1},	/* ARG_STA_FF */	\
!   {ARG_STA_FGF,ARG_STA_FGG,ARG_STA_FGD,-1,7,-1}, /* ARG_STA_FG */	\
!   {ARG_STA_FGF,ARG_STA_FGF,ARG_STA_FGF,-1,-1,-1}, /* ARG_STA_FGF */	\
!   {ARG_STA_FGG,ARG_STA_FGG,ARG_STA_FGG,-1,-1,-1}, /* ARG_STA_FGG */	\
!   {ARG_STA_FGD,ARG_STA_FGD,ARG_STA_FGD,-1,-1,-1}, /* ARG_STA_FGD */	\
!   {ARG_STA_FD,ARG_STA_FD,ARG_STA_FD,-1,-1,-1},	/* ARG_STA_FD */	\
!   {ARG_STA_GF,ARG_STA_GG,ARG_STA_GD,-2,5,6},	/* ARG_STA_G */		\
!   {ARG_STA_GF,ARG_STA_GF,ARG_STA_GF,-1,-1,-1},	/* ARG_STA_GF */	\
!   {ARG_STA_GGF,ARG_STA_GGG,ARG_STA_GGD,-2,6,6},	/* ARG_STA_GG */	\
!   {ARG_STA_GGF,ARG_STA_GGF,ARG_STA_GGF,-1,-1,-1}, /* ARG_STA_GGF */	\
!   {ARG_STA_GGGF,ARG_STA_GGGG,ARG_STA_GGGD,-1,7,-1}, /* ARG_STA_GGG */	\
!   {ARG_STA_GGGF,ARG_STA_GGGF,ARG_STA_GGGF,-1,-1,-1}, /* ARG_STA_GGGF */	\
!   {ARG_STA_GGGG,ARG_STA_GGGG,ARG_STA_GGGG,-1,-1,-1}, /* ARG_STA_GGGG */	\
!   {ARG_STA_GGGD,ARG_STA_GGGD,ARG_STA_GGGD,-1,-1,-1}, /* ARG_STA_GGGD */	\
!   {ARG_STA_GGD,ARG_STA_GGD,ARG_STA_GGD,-1,-1,-1}, /* ARG_STA_GGD */	\
!   {ARG_STA_GD,ARG_STA_GD,ARG_STA_GD,-1,-1,-1},	/* ARG_STA_GD */	\
!   {ARG_STA_DF,ARG_STA_DG,ARG_STA_DD,-2,6,6},	/* ARG_STA_D */		\
!   {ARG_STA_DF,ARG_STA_DF,ARG_STA_DF,-1,-1,-1},	/* ARG_STA_DF */	\
!   {ARG_STA_DGF,ARG_STA_DGG,ARG_STA_DGD,-1,7,-1}, /* ARG_STA_DG */	\
!   {ARG_STA_DGF,ARG_STA_DGF,ARG_STA_DGF,-1,-1,-1}, /* ARG_STA_DGF */	\
!   {ARG_STA_DGG,ARG_STA_DGG,ARG_STA_DGG,-1,-1,-1}, /* ARG_STA_DGG */	\
!   {ARG_STA_DGD,ARG_STA_DGD,ARG_STA_DGD,-1,-1,-1}, /* ARG_STA_DGD */	\
!   {ARG_STA_DD,ARG_STA_DD,ARG_STA_DD,-1,-1,-1}	/* ARG_STA_DD */	\
  }
  
+ typedef struct { enum arg_state arg_rec_state;int restype,arg_num;} cumulative_args_t;
+ 
  /* Initialize a variable CUM of type CUMULATIVE_ARGS
     for a call to a function whose data type is FNTYPE.