Cleanup, and make prologue issue schedulable insns.
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Jul 1992 15:20:56 +0000 (15:20 +0000)
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Jul 1992 15:20:56 +0000 (15:20 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@1660 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md

index b8f4861..994642c 100644 (file)
@@ -62,37 +62,38 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define STAB_CODE_TYPE int
 #endif
 
-extern char *getenv ();
-
-extern char *permalloc ();
-extern void  debug_rtx ();
-extern void  abort_with_insn ();
-extern rtx   copy_to_reg ();
-extern rtx   adj_offsettable_operand ();
-extern int   offsettable_address_p ();
-extern tree  lookup_name ();
-
-extern rtx gen_movqi ();
-extern rtx gen_movhi ();
-extern rtx gen_movsi ();
-extern rtx gen_movsi_ulw ();
-extern rtx gen_movsi_usw ();
-extern rtx gen_movstrsi_internal ();
-extern rtx gen_addsi3 ();
-extern rtx gen_iorsi3 ();
-extern rtx gen_andsi3 ();
-extern rtx gen_bne ();
-extern rtx gen_beq ();
-extern rtx gen_cmpsi ();
-extern rtx gen_jump ();
-
-extern char   call_used_regs[];
-extern char  *asm_file_name;
-extern FILE  *asm_out_file;
+extern void   abort ();
+extern int    atoi ();
+extern char  *getenv ();
+extern char  *mktemp ();
+extern rtx    adj_offsettable_operand ();
+extern rtx    copy_to_reg ();
+extern void   error ();
+extern void   fatal ();
+extern tree   lookup_name ();
+extern void   pfatal_with_name ();
+extern void   warning ();
+
+extern rtx    gen_addsi3 ();
+extern rtx    gen_andsi3 ();
+extern rtx    gen_beq ();
+extern rtx    gen_bne ();
+extern rtx    gen_cmpsi ();
+extern rtx    gen_indirect_jump ();
+extern rtx    gen_iorsi3 ();
+extern rtx    gen_jump ();
+extern rtx    gen_movhi ();
+extern rtx    gen_movqi ();
+extern rtx    gen_movsi ();
+extern rtx    gen_movsi_ulw ();
+extern rtx    gen_movsi_usw ();
+extern rtx    gen_movstrsi_internal ();
+extern rtx    gen_return_internal ();
+extern rtx    gen_subsi3 ();
+
 extern tree   current_function_decl;
-extern char **save_argv;
-extern char  *version_string;
-extern char  *language_string;
+extern FILE  *asm_out_file;
 
 /* Enumeration for all of the relational tests, so that we can build
    arrays indexed by the test type, and not worry about the order
@@ -447,6 +448,9 @@ reg_or_0_operand (op, mode)
 {
   switch (GET_CODE (op))
     {
+    default:
+      break;
+
     case CONST_INT:
       return (INTVAL (op) == 0);
 
@@ -558,6 +562,9 @@ simple_memory_operand (op, mode)
   addr = XEXP (op, 0);
   switch (GET_CODE (addr))
     {
+    default:
+      break;
+
     case REG:
       return TRUE;
 
@@ -819,6 +826,9 @@ mips_count_memory_refs (op, num)
       looping = FALSE;
       switch (GET_CODE (addr))
        {
+       default:
+         break;
+
        case REG:
        case CONST_INT:
          break;
@@ -1013,6 +1023,7 @@ mips_move_1word (operands, insn, unsignedp)
                 target, so zero/sign extend can use this code as well.  */
              switch (GET_MODE (op1))
                {
+               default:      break;
                case SFmode: ret = "lw\t%0,%1"; break;
                case SImode: ret = "lw\t%0,%1"; break;
                case HImode: ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1"; break;
@@ -1049,7 +1060,7 @@ mips_move_1word (operands, insn, unsignedp)
            }
 
          else if (GP_REG_P (regno0))
-           ret = (INTVAL (op1) < 0) ? "li\t%0,%1\t\t# %X1" : "li\t%0,%X1\t\t# %1";
+           ret = (INTVAL (op1) < 0) ? "li\t%0,%1\t\t\t# %X1" : "li\t%0,%X1\t\t# %1";
        }
 
       else if (code1 == CONST_DOUBLE && mode == SFmode)
@@ -1121,6 +1132,7 @@ mips_move_1word (operands, insn, unsignedp)
            {
              switch (mode)
                {
+               default: break;
                case SFmode: ret = "sw\t%1,%0"; break;
                case SImode: ret = "sw\t%1,%0"; break;
                case HImode: ret = "sh\t%1,%0"; break;
@@ -1136,6 +1148,7 @@ mips_move_1word (operands, insn, unsignedp)
        {
          switch (mode)
            {
+           default: break;
            case SFmode: ret = "sw\t%z1,%0"; break;
            case SImode: ret = "sw\t%z1,%0"; break;
            case HImode: ret = "sh\t%z1,%0"; break;
@@ -1147,6 +1160,7 @@ mips_move_1word (operands, insn, unsignedp)
        {
          switch (mode)
            {
+           default: break;
            case SFmode: ret = "sw\t%.,%0"; break;
            case SImode: ret = "sw\t%.,%0"; break;
            case HImode: ret = "sh\t%.,%0"; break;
@@ -1274,8 +1288,8 @@ mips_move_2words (operands, insn)
 
              else
                {
-                 operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1));
-                 operands[3] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1));
+                 operands[2] = GEN_INT (CONST_DOUBLE_LOW (op1));
+                 operands[3] = GEN_INT (CONST_DOUBLE_HIGH (op1));
                  ret = "li\t%M0,%3\n\tli\t%L0,%2";
                }
            }
@@ -1311,7 +1325,7 @@ mips_move_2words (operands, insn)
        
       else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0))
        {
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) >= 0 ? 0 : -1);
+         operands[2] = GEN_INT (INTVAL (operands[1]) >= 0 ? 0 : -1);
          ret = "li\t%M0,%2\n\tli\t%L0,%1";
        }
 
@@ -1412,6 +1426,9 @@ mips_address_cost (addr)
 {
   switch (GET_CODE (addr))
     {
+    default:
+      break;
+
     case LO_SUM:
     case HIGH:
       return 1;
@@ -1453,6 +1470,9 @@ mips_address_cost (addr)
 
        switch (GET_CODE (plus1))
          {
+         default:
+           break;
+
          case CONST_INT:
            {
              int value = INTVAL (plus1);
@@ -1483,6 +1503,7 @@ map_test_to_internal_test (test_code)
 
   switch (test_code)
     {
+    default:                   break;
     case EQ:  test = ITEST_EQ;  break;
     case NE:  test = ITEST_NE;  break;
     case GT:  test = ITEST_GT;  break;
@@ -1645,7 +1666,7 @@ gen_int_relational (test_code, result, cmp0, cmp1, p_invert)
   if (GET_CODE (cmp1) == CONST_INT)
     {
       if (p_info->const_add != 0)
-       cmp1 = gen_rtx (CONST_INT, VOIDmode, INTVAL (cmp1) + p_info->const_add);
+       cmp1 = GEN_INT (INTVAL (cmp1) + p_info->const_add);
     }
   else if (p_info->reverse_regs)
     {
@@ -1809,6 +1830,7 @@ fail:
 /* Internal code to generate the load and store of one word/short/byte.
    The load is emitted directly, and the store insn is returned.  */
 
+#if 0
 static rtx
 block_move_load_store (dest_reg, src_reg, p_bytes, p_offset, align, orig_src)
      rtx src_reg;              /* register holding source memory address */
@@ -1881,8 +1903,8 @@ block_move_load_store (dest_reg, src_reg, p_bytes, p_offset, align, orig_src)
     }
   else
     {
-      src_addr  = gen_rtx (PLUS, Pmode, src_reg,  gen_rtx (CONST_INT, VOIDmode, offset));
-      dest_addr = gen_rtx (PLUS, Pmode, dest_reg, gen_rtx (CONST_INT, VOIDmode, offset));
+      src_addr  = gen_rtx (PLUS, Pmode, src_reg,  GEN_INT (offset));
+      dest_addr = gen_rtx (PLUS, Pmode, dest_reg, GEN_INT (offset));
     }
 
   reg = gen_reg_rtx (mode);
@@ -1895,6 +1917,7 @@ block_move_load_store (dest_reg, src_reg, p_bytes, p_offset, align, orig_src)
 
   return (*store_func) (gen_rtx (MEM, mode, dest_addr), reg);
 }
+#endif
 
 \f
 /* Write a series of loads/stores to move some bytes.  Generate load/stores as follows:
@@ -1913,6 +1936,7 @@ block_move_load_store (dest_reg, src_reg, p_bytes, p_offset, align, orig_src)
    two temp registers are needed.  Two delay slots are used
    in deference to the R4000.  */
 
+#if 0
 static void
 block_move_sequence (dest_reg, src_reg, bytes, align, orig_src)
      rtx dest_reg;             /* register holding destination address */
@@ -1949,6 +1973,7 @@ block_move_sequence (dest_reg, src_reg, bytes, align, orig_src)
   if (cur_store)
     emit_insn (cur_store);
 }
+#endif
 
 \f
 /* Write a loop to move a constant number of bytes.  Generate load/stores as follows:
@@ -1986,11 +2011,10 @@ block_move_loop (dest_reg, src_reg, bytes, align, orig_src)
 {
   rtx dest_mem         = gen_rtx (MEM, BLKmode, dest_reg);
   rtx src_mem          = gen_rtx (MEM, BLKmode, src_reg);
-  rtx align_rtx                = gen_rtx (CONST_INT, VOIDmode, align);
+  rtx align_rtx                = GEN_INT (align);
   rtx label;
   rtx final_src;
   rtx bytes_rtx;
-  int i;
   int leftover;
 
   if (bytes < 2*MAX_MOVE_BYTES)
@@ -2001,7 +2025,7 @@ block_move_loop (dest_reg, src_reg, bytes, align, orig_src)
 
   label = gen_label_rtx ();
   final_src = gen_reg_rtx (Pmode);
-  bytes_rtx = gen_rtx (CONST_INT, VOIDmode, bytes);
+  bytes_rtx = GEN_INT (bytes);
 
   if (bytes > 0x7fff)
     {
@@ -2013,7 +2037,7 @@ block_move_loop (dest_reg, src_reg, bytes, align, orig_src)
 
   emit_label (label);
 
-  bytes_rtx = gen_rtx (CONST_INT, VOIDmode, MAX_MOVE_BYTES);
+  bytes_rtx = GEN_INT (MAX_MOVE_BYTES);
   emit_insn (gen_movstrsi_internal (dest_mem, src_mem, bytes_rtx, align_rtx));
   emit_insn (gen_addsi3 (src_reg, src_reg, bytes_rtx));
   emit_insn (gen_addsi3 (dest_reg, dest_reg, bytes_rtx));
@@ -2022,7 +2046,7 @@ block_move_loop (dest_reg, src_reg, bytes, align, orig_src)
 
   if (leftover)
     emit_insn (gen_movstrsi_internal (dest_mem, src_mem,
-                                     gen_rtx (CONST_INT, VOIDmode, leftover),
+                                     GEN_INT (leftover),
                                      align_rtx));
 }
 
@@ -2111,7 +2135,7 @@ expand_block_move (operands)
       bytes -= leftover;
 
       emit_insn (gen_iorsi3 (temp, src_reg, dest_reg));
-      emit_insn (gen_andsi3 (temp, temp, gen_rtx (CONST_INT, VOIDmode, UNITS_PER_WORD-1)));
+      emit_insn (gen_andsi3 (temp, temp, GEN_INT (UNITS_PER_WORD-1)));
       emit_insn (gen_cmpsi (temp, const0_rtx));
       emit_jump_insn (gen_beq (aligned_label));
 
@@ -2136,8 +2160,8 @@ expand_block_move (operands)
 #endif
            emit_insn (gen_movstrsi_internal (gen_rtx (MEM, BLKmode, dest_reg),
                                              gen_rtx (MEM, BLKmode, src_reg),
-                                             gen_rtx (CONST_INT, VOIDmode, leftover),
-                                             gen_rtx (CONST_INT, VOIDmode, align)));
+                                             GEN_INT (leftover),
+                                             GEN_INT (align)));
        }
     }
 
@@ -2458,6 +2482,7 @@ function_arg_advance (cum, mode, type, named)
      CUMULATIVE_ARGS *cum;     /* current arg information */
      enum machine_mode mode;   /* current arg mode */
      tree type;                        /* type of the argument or 0 if lib support */
+     int named;                        /* whether or not the argument was named */
 {
   if (TARGET_DEBUG_E_MODE)
     fprintf (stderr,
@@ -3569,7 +3594,6 @@ final_prescan_insn (insn, opvec, noperands)
 {
   if (dslots_number_nops > 0)
     {
-      enum machine_mode mode = GET_MODE (mips_load_reg);
       rtx pattern = PATTERN (insn);
       int length = get_attr_length (insn);
 
@@ -3892,6 +3916,8 @@ compute_frame_size (size)
   current_frame_info.mask       = mask;
   current_frame_info.fmask      = fmask;
   current_frame_info.initialized = reload_completed;
+  current_frame_info.num_gp     = gp_reg_size / UNITS_PER_WORD;
+  current_frame_info.num_fp     = fp_reg_size / (2*UNITS_PER_WORD);
 
   if (mask)
     {
@@ -3912,7 +3938,7 @@ compute_frame_size (size)
 }
 
 \f
-/* Common code to save/restore registers.  */
+/* Save/restore registers printing out the instructions to a file.  */
 
 void
 save_restore (file, gp_op, gp_2word_op, fp_op)
@@ -3987,6 +4013,89 @@ save_restore (file, gp_op, gp_2word_op, fp_op)
 }
 
 \f
+/* Common code to emit the insns to save/restore registers.  */
+
+static void
+save_restore_insns (store_p)
+     int store_p;              /* true if this is prologue */
+{
+  int regno;
+  rtx base_reg_rtx       = stack_pointer_rtx;
+  unsigned long mask     = current_frame_info.mask;
+  unsigned long fmask    = current_frame_info.fmask;
+  unsigned long gp_offset;
+  unsigned long fp_offset;
+  unsigned long max_offset;
+
+  if (mask == 0 && fmask == 0)
+    return;
+
+  gp_offset  = current_frame_info.gp_sp_offset;
+  fp_offset  = current_frame_info.fp_sp_offset;
+  max_offset = (gp_offset > fp_offset) ? gp_offset : fp_offset;
+
+  /* Deal with calling functions with a large structure.  */
+  if (max_offset >= 32768)
+    {
+      base_reg_rtx = gen_rtx (REG, Pmode, MIPS_TEMP2_REGNUM);
+      emit_move_insn (base_reg_rtx, GEN_INT (max_offset));
+      emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, stack_pointer_rtx));
+      gp_offset = max_offset - gp_offset;
+      fp_offset = max_offset - fp_offset;
+    }
+
+  /* Save registers starting from high to low.  The debuggers prefer
+     at least the return register be stored at func+4, and also it
+     allows us not to need a nop in the epilog if at least one
+     register is reloaded in addition to return address.  */
+
+  if (mask || frame_pointer_needed)
+    {
+      for  (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
+       {
+         if ((mask & (1L << (regno - GP_REG_FIRST))) != 0
+             || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed))
+           {
+             rtx reg_rtx = gen_rtx (REG, Pmode, regno);
+             rtx mem_rtx = gen_rtx (MEM, Pmode,
+                                    gen_rtx (PLUS, Pmode, base_reg_rtx,
+                                             GEN_INT (gp_offset)));
+
+             if (store_p)
+               emit_move_insn (mem_rtx, reg_rtx);
+             else
+               emit_move_insn (reg_rtx, mem_rtx);
+
+             gp_offset -= UNITS_PER_WORD;
+           }
+       }
+    }
+
+  if (fmask)
+    {
+      int fp_inc = (TARGET_FLOAT64) ? 1 : 2;
+
+      for  (regno = FP_REG_LAST-1; regno >= FP_REG_FIRST; regno -= fp_inc)
+       {
+         if ((fmask & (1L << (regno - FP_REG_FIRST))) != 0)
+           {
+             rtx reg_rtx = gen_rtx (REG, DFmode, regno);
+             rtx mem_rtx = gen_rtx (MEM, DFmode,
+                                    gen_rtx (PLUS, Pmode, base_reg_rtx,
+                                             GEN_INT (fp_offset)));
+
+             if (store_p)
+               emit_move_insn (mem_rtx, reg_rtx);
+             else
+               emit_move_insn (reg_rtx, mem_rtx);
+
+             fp_offset -= 2*UNITS_PER_WORD;
+           }
+       }
+    }
+}
+
+\f
 /* Set up the stack and frame (if desired) for the function.  */
 
 void
@@ -3994,21 +4103,9 @@ function_prologue (file, size)
      FILE *file;
      int size;
 {
-  int regno;
-  int tsize;
-  char *sp_str = reg_names[STACK_POINTER_REGNUM];
-  char *fp_str = (!frame_pointer_needed)
-                       ? sp_str
-                       : reg_names[FRAME_POINTER_REGNUM];
-  tree fndecl = current_function_decl; /* current... is tooo long */
-  tree fntype = TREE_TYPE (fndecl);
-  tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE)
-                       ? DECL_ARGUMENTS (fndecl)
-                       : 0;
-  tree next_arg;
-  tree cur_arg;
-  char *arg_name = (char *)0;
-  CUMULATIVE_ARGS args_so_far;
+  int tsize = current_frame_info.total_size;
+  int vframe;
+  int vreg;
 
   ASM_OUTPUT_SOURCE_FILENAME (file, DECL_SOURCE_FILE (current_function_decl));
   ASM_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl));
@@ -4025,6 +4122,57 @@ function_prologue (file, size)
             "\t.set\tnoreorder\n\t.cpload\t%s\n\t.set\treorder\n",
             reg_names[ GP_REG_FIRST + 25 ]);
 
+  tsize = current_frame_info.total_size;
+  if (tsize > 0 && TARGET_ABICALLS)
+    fprintf (file, "\t.cprestore %d\n", tsize + STARTING_FRAME_OFFSET);
+
+  if (frame_pointer_needed)
+    {
+      vframe = 0;
+      vreg   = FRAME_POINTER_REGNUM;
+    }
+  else
+    {
+      vframe = tsize;
+      vreg   = STACK_POINTER_REGNUM;
+    }
+
+  fprintf (file, "\t.frame\t%s,%d,%s\t\t# vars= %d, regs= %d/%d, args = %d, extra= %d\n",
+          reg_names[ vreg ],
+          vframe,
+          reg_names[31 + GP_REG_FIRST],
+          current_frame_info.var_size,
+          current_frame_info.num_gp,
+          current_frame_info.num_fp,
+          current_function_outgoing_args_size,
+          current_frame_info.extra_size);
+
+  fprintf (file, "\t.mask\t0x%08lx,%d\n\t.fmask\t0x%08lx,%d\n",
+          current_frame_info.mask,
+          current_frame_info.gp_save_offset,
+          current_frame_info.fmask,
+          current_frame_info.fp_save_offset);
+}
+
+\f
+/* Expand the prologue into a bunch of separate insns.  */
+
+void
+mips_expand_prologue ()
+{
+  int regno;
+  int size;
+  int tsize;
+  tree fndecl = current_function_decl; /* current... is tooo long */
+  tree fntype = TREE_TYPE (fndecl);
+  tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE)
+                       ? DECL_ARGUMENTS (fndecl)
+                       : 0;
+  tree next_arg;
+  tree cur_arg;
+  char *arg_name = (char *)0;
+  CUMULATIVE_ARGS args_so_far;
+
   /* Determine the last argument, and get its name.  */
   for (cur_arg = fnargs; cur_arg != (tree)0; cur_arg = next_arg)
     {
@@ -4084,68 +4232,37 @@ function_prologue (file, size)
                                DECL_ARG_TYPE (parm), 1);
        }
 
-      if (regno <= GP_ARG_LAST && (regno & 1) != 0)
+      for (; regno <= GP_ARG_LAST; regno++)
        {
-         fprintf (file, "\tsw\t%s,%d(%s)\t\t# varargs home register\n",
-                  reg_names[regno], (regno - 4) * 4, sp_str);
-         regno++;
-       }
+         rtx ptr = stack_pointer_rtx;
+         if (regno != GP_ARG_FIRST)
+           ptr = gen_rtx (PLUS, Pmode, ptr,
+                          GEN_INT ((regno - GP_ARG_FIRST) * UNITS_PER_WORD));
 
-      for (; regno <= GP_ARG_LAST; regno += 2)
-       {
-         fprintf (file, "\tsd\t%s,%d(%s)\t\t# varargs home register\n",
-                  reg_names[regno], (regno - 4) * 4, sp_str);
+         emit_move_insn (gen_rtx (MEM, Pmode, ptr), gen_rtx (REG, Pmode, regno));
        }
     }
 
-  size = MIPS_STACK_ALIGN (size);
-  tsize = (!current_frame_info.initialized)
-               ? compute_frame_size (size)
-               : current_frame_info.total_size;
+  size  = MIPS_STACK_ALIGN (get_frame_size ());
+  tsize = compute_frame_size (size);
 
   if (tsize > 0)
     {
-      if (tsize <= 32767)
-       fprintf (file,
-                "\tsubu\t%s,%s,%d\t\t# vars= %d, regs= %d/%d, args = %d, extra= %d\n",
-                sp_str, sp_str, tsize, current_frame_info.var_size,
-                current_frame_info.gp_reg_size / 4,
-                current_frame_info.fp_reg_size / 8,
-                current_function_outgoing_args_size,
-                current_frame_info.extra_size);
-      else
-       fprintf (file,
-                "\tli\t%s,%d\n\tsubu\t%s,%s,%s\t\t# vars= %d, regs= %d/%d, args = %d, sfo= %d\n",
-                reg_names[MIPS_TEMP1_REGNUM], tsize, sp_str, sp_str,
-                reg_names[MIPS_TEMP1_REGNUM], current_frame_info.var_size,
-                current_frame_info.gp_reg_size / 4,
-                current_frame_info.fp_reg_size / 8,
-                current_function_outgoing_args_size,
-                current_frame_info.extra_size);
-    }
+      rtx tsize_rtx = GEN_INT (tsize);
 
-  if (TARGET_ABICALLS)
-    fprintf (file, "\t.cprestore %d\n", tsize + STARTING_FRAME_OFFSET);
-
-  fprintf (file, "\t.frame\t%s,%d,%s\n\t.mask\t0x%08lx,%d\n\t.fmask\t0x%08lx,%d\n",
-          fp_str,
-          (frame_pointer_needed) ? 0 : tsize,
-          reg_names[31 + GP_REG_FIRST],
-          current_frame_info.mask,
-          current_frame_info.gp_save_offset,
-          current_frame_info.fmask,
-          current_frame_info.fp_save_offset);
+      if (tsize > 32767)
+       {
+         rtx tmp_rtx = gen_rtx (REG, SImode, MIPS_TEMP1_REGNUM);
+         emit_move_insn (tmp_rtx, tsize_rtx);
+         tsize_rtx = tmp_rtx;
+       }
 
-  save_restore (file, "sw", "sd", "s.d");
+      emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tsize_rtx));
 
-  if (frame_pointer_needed)
-    {
-      if (tsize <= 32767)
-       fprintf (file, "\taddu\t%s,%s,%d\t\t# set up frame pointer\n", fp_str, sp_str, tsize);
+      save_restore_insns (TRUE);
 
-      else
-       fprintf (file, "\taddu\t%s,%s,%s\t\t# set up frame pointer\n", fp_str, sp_str,
-                reg_names[MIPS_TEMP1_REGNUM]);
+      if (frame_pointer_needed)
+       emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx, tsize_rtx));
     }
 }
 
@@ -4391,6 +4508,35 @@ function_epilogue (file, size)
 }
 
 \f
+/* Expand the epilogue into a bunch of separate insns.  */
+
+void
+mips_expand_epilogue ()
+{
+  int tsize = current_frame_info.total_size;
+  rtx tsize_rtx = GEN_INT (tsize);
+
+  if (tsize > 32767)
+    {
+      rtx tmp_rtx = gen_rtx (REG, SImode, MIPS_TEMP1_REGNUM);
+      emit_move_insn (tmp_rtx, tsize_rtx);
+      tsize_rtx = tmp_rtx;
+    }
+
+  if (tsize > 0)
+    {
+      if (frame_pointer_needed)
+       emit_insn (gen_subsi3 (stack_pointer_rtx, frame_pointer_rtx, tsize_rtx));
+
+      save_restore_insns (FALSE);
+
+      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tsize_rtx));
+    }
+
+  emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode, GP_REG_FIRST+31)));
+}
+
+\f
 /* Define the number of delay slots needed for the function epilogue.
 
    On the mips, we need a slot if either no stack has been allocated,
@@ -4417,7 +4563,7 @@ mips_epilogue_delay_slots ()
    was created.  */
 
 int
-null_epilogue ()
+simple_epilogue_p ()
 {
   if (!reload_completed)
     return 0;
index 714a02a..c0bf947 100644 (file)
@@ -28,12 +28,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* Standard GCC variables that we reference.  */
 
-extern int target_flags;
-extern int optimize;
-extern int may_call_alloca;
-extern int current_function_calls_alloca;
-extern int frame_pointer_needed;
-extern int flag_omit_frame_pointer;
+extern char    *asm_file_name;
+extern char    call_used_regs[];
+extern int     current_function_calls_alloca;
+extern int     flag_omit_frame_pointer;
+extern int     frame_pointer_needed;
+extern char    *language_string;
+extern int     may_call_alloca;
+extern int     optimize;
+extern char   **save_argv;
+extern int     target_flags;
+extern char    *version_string;
 
 /* MIPS external variables defined in mips.c.  */
 
@@ -140,11 +145,13 @@ extern int                md_register_operand ();
 extern int             mips_address_cost ();
 extern void            mips_asm_file_end ();
 extern void            mips_asm_file_start ();
-extern void            mips_declare_object ();
 extern int             mips_const_double_ok ();
 extern void            mips_count_memory_refs ();
 extern int             mips_debugger_offset ();
+extern void            mips_declare_object ();
 extern int             mips_epilogue_delay_slots ();
+extern void            mips_expand_epilogue ();
+extern void            mips_expand_prologue ();
 extern char           *mips_fill_delay_slot ();
 extern char           *mips_move_1word ();
 extern char           *mips_move_2words ();
@@ -160,19 +167,50 @@ extern void               print_operand_address ();
 extern void            print_operand ();
 extern void            print_options ();
 extern int             reg_or_0_operand ();
+extern int             simple_epilogue_p ();
 extern int             simple_memory_operand ();
 extern int             small_int ();
 extern void            trace();
 extern int             uns_arith_operand ();
 extern int             uns_cmp_op ();
 
-/* Functions in varasm.c that we reference.  */
+/* Recognition functions that return if a condition is true.  */
+extern int             address_operand ();
+extern int             const_double_operand ();
+extern int             const_int_operand ();
+extern int             general_operand ();
+extern int             immediate_operand ();
+extern int             memory_address_p ();
+extern int             memory_operand ();
+extern int             nonimmediate_operand ();
+extern int             nonmemory_operand ();
+extern int             register_operand ();
+extern int             scratch_operand ();
+
+/* Functions to change what output section we are using.  */
 extern void            data_section ();
 extern void            rdata_section ();
 extern void            readonly_data_section ();
 extern void            sdata_section ();
 extern void            text_section ();
 
+/* Functions in the rest of the compiler that we reference.  */
+extern void            abort_with_insn ();
+extern void            debug_rtx ();
+extern void            fatal_io_error ();
+extern int             get_frame_size ();
+extern int             offsettable_address_p ();
+extern void            output_address ();
+extern char           *permalloc ();
+extern int             reg_mentioned_p ();
+
+/* Functions in the standard library that we reference.  */
+extern void            abort ();
+extern int             atoi ();
+extern char           *getenv ();
+extern char           *mktemp ();
+
+
 /* Stubs for half-pic support if not OSF/1 reference platform.  */
 
 #ifndef HALF_PIC_P
@@ -435,7 +473,7 @@ while (0)
 \f
 /* Print subsidiary information on the compiler version in use.  */
 
-#define MIPS_VERSION "[AL 1.1, MM 21]"
+#define MIPS_VERSION "[AL 1.1, MM 22]"
 
 #ifndef MACHINE_TYPE
 #define MACHINE_TYPE "BSD Mips"
@@ -1143,13 +1181,13 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 /* #define PC_REGNUM xx                                */
 
 /* Register to use for pushing function arguments.  */
-#define STACK_POINTER_REGNUM 29
+#define STACK_POINTER_REGNUM (GP_REG_FIRST + 29)
 
 /* Offset from the stack pointer to the first available location.  */
 #define STACK_POINTER_OFFSET 0
 
 /* Base register for access to local variables of the function.  */
-#define FRAME_POINTER_REGNUM 30
+#define FRAME_POINTER_REGNUM (GP_REG_FIRST + 30)
 
 /* Value should be nonzero if functions must have frame pointers.
    Zero means the frame pointer need not be set up (and parms
@@ -1161,19 +1199,19 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 #define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
 
 /* Register in which static-chain is passed to a function.  */
-#define STATIC_CHAIN_REGNUM 2
+#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 2)
 
 /* Register in which address to store a structure value
    is passed to a function.  */
-#define STRUCT_VALUE_REGNUM 4
+#define STRUCT_VALUE_REGNUM (GP_REG_FIRST + 4)
 
 /* Mips registers used in prologue/epilogue code when the stack frame
    is larger than 32K bytes.  These registers must come from the
    scratch register set, and not used for passing and returning
    arguments and any other information used in the calling sequence
    (such as pic).  */
-#define MIPS_TEMP1_REGNUM 8
-#define MIPS_TEMP2_REGNUM 9
+#define MIPS_TEMP1_REGNUM (GP_REG_FIRST + 8)
+#define MIPS_TEMP2_REGNUM (GP_REG_FIRST + 9)
 
 /* Define this macro if it is as good or better to call a constant
    function address than to call an address kept in a register.  */
@@ -1191,7 +1229,7 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
    once, as with the stack pointer and frame pointer registers.  If
    this macro is not defined, it is up to the machine-dependent
    files to allocate such a register (if necessary).  */
-#define PIC_OFFSET_TABLE_REGNUM 28
+#define PIC_OFFSET_TABLE_REGNUM (GP_REG_FIRST + 28)
 
 \f
 /* Define the classes of registers for register constraints in the
@@ -1400,6 +1438,21 @@ extern enum reg_class mips_char_to_class[];
                ? GR_REGS                                               \
                : CLASS))
 
+/* Certain machines have the property that some registers cannot be
+   copied to some other registers without using memory.  Define this
+   macro on those machines to be a C expression that is non-zero if
+   objects of mode MODE in registers of CLASS1 can only be copied to
+   registers of class CLASS2 by storing a register of CLASS1 into
+   memory and loading that memory location into a register of CLASS2.
+
+   Do not define this macro if its value would always be zero.  */
+
+#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE)                  \
+  (!TARGET_DEBUG_H_MODE                                                        \
+   && GET_MODE_CLASS (MODE) == MODE_INT                                        \
+   && ((CLASS1 == FP_REGS && CLASS2 == GR_REGS)                                \
+       || (CLASS1 == GR_REGS && CLASS2 == FP_REGS)))
+
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.  */
 
@@ -1458,6 +1511,8 @@ struct mips_frame_info
   unsigned long gp_sp_offset;  /* offset from new sp to store gp registers */
   unsigned long fp_sp_offset;  /* offset from new sp to store fp registers */
   int          initialized;    /* != 0 if frame size already calculated */
+  int          num_gp;         /* number of gp registers saved */
+  int          num_fp;         /* number of fp registers saved */
 };
 
 extern struct mips_frame_info current_frame_info;
index 65c9764..0d56e2f 100644 (file)
@@ -1892,15 +1892,28 @@ move\\t%0,%z4\\n\\
     }
 }")
 
-(define_insn "movsi_internal"
+;; The difference between these two is whether or not ints are allowed
+;; in FP registers (off by default, use -mdebugh to enable).
+
+(define_insn "movsi_internal1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*fz,*f,*f,*f,*R,*m,*x,*d")
        (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*fz,*d,*f,*R,*m,*f,*f,*d,*x"))]
-  ""
+  "TARGET_DEBUG_H_MODE"
   "* return mips_move_1word (operands, insn, TRUE);"
   [(set_attr "type"    "move,pic,arith,arith,load,load,store,store,xfer,xfer,move,load,load,store,store,hilo,hilo")
    (set_attr "mode"    "SI")
    (set_attr "length"  "1,4,1,2,1,2,1,2,1,1,1,1,2,1,2,1,1")])
 
+(define_insn "movsi_internal2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*d,*x")
+       (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,*x,*d"))]
+  "!TARGET_DEBUG_H_MODE"
+  "* return mips_move_1word (operands, insn, TRUE);"
+  [(set_attr "type"    "move,pic,arith,arith,load,load,store,store,xfer,xfer,hilo,hilo")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "1,4,1,2,1,2,1,2,1,1,1,1")])
+
+
 ;; 16-bit Integer moves
 
 ;; Unlike most other insns, the move insns can't be split with
@@ -1908,15 +1921,34 @@ move\\t%0,%z4\\n\\
 ;; the compiler, have memoized the insn number already.
 ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined
 
-(define_insn "movhi"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f,*x,*d")
-       (match_operand:HI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*fz,*d,*f,*d,*x"))]
+(define_expand "movhi"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "")
+       (match_operand:HI 1 "general_operand" ""))]
   ""
+  "")
+
+;; The difference between these two is whether or not ints are allowed
+;; in FP registers (off by default, use -mdebugh to enable).
+
+(define_insn "movhi_internal1"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*fz,*x,*d")
+       (match_operand:HI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*fz,*d,*f,*d,*x"))]
+  "TARGET_DEBUG_H_MODE"
   "* return mips_move_1word (operands, insn, TRUE);"
   [(set_attr "type"    "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo")
    (set_attr "mode"    "HI")
    (set_attr "length"  "1,1,1,2,1,2,1,1,1,1,1")])
 
+(define_insn "movhi_internal2"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d")
+       (match_operand:HI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))]
+  "!TARGET_DEBUG_H_MODE"
+  "* return mips_move_1word (operands, insn, TRUE);"
+  [(set_attr "type"    "move,arith,load,load,store,store,xfer,xfer,hilo,hilo")
+   (set_attr "mode"    "HI")
+   (set_attr "length"  "1,1,1,2,1,2,1,1,1,1")])
+
+
 ;; 8-bit Integer moves
 
 ;; Unlike most other insns, the move insns can't be split with
@@ -1924,15 +1956,33 @@ move\\t%0,%z4\\n\\
 ;; the compiler, have memoized the insn number already.
 ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined
 
-(define_insn "movqi"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f,*x,*d")
-       (match_operand:QI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*fz,*d,*f,*d,*x"))]
+(define_expand "movqi"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "")
+       (match_operand:QI 1 "general_operand" ""))]
   ""
+  "")
+
+;; The difference between these two is whether or not ints are allowed
+;; in FP registers (off by default, use -mdebugh to enable).
+
+(define_insn "movqi_internal1"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*fz,*f,*x,*d")
+       (match_operand:QI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*fz,*d,*f,*d,*x"))]
+  "TARGET_DEBUG_H_MODE"
   "* return mips_move_1word (operands, insn, TRUE);"
   [(set_attr "type"    "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo")
    (set_attr "mode"    "QI")
    (set_attr "length"  "1,1,1,2,1,2,1,1,1,1,1")])
 
+(define_insn "movqi_internal2"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d")
+       (match_operand:QI 1 "general_operand"       "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))]
+  "!TARGET_DEBUG_H_MODE"
+  "* return mips_move_1word (operands, insn, TRUE);"
+  [(set_attr "type"    "move,arith,load,load,store,store,xfer,xfer,hilo,hilo")
+   (set_attr "mode"    "QI")
+   (set_attr "length"  "1,1,1,2,1,2,1,1,1,1")])
+
 
 ;; 32-bit floating point moves
 
@@ -2117,7 +2167,7 @@ move\\t%0,%z4\\n\\
 
 
 (define_insn "ashldi3_internal"
-  [(set (match_operand:DI 0 "register_operand" "=d")
+  [(set (match_operand:DI 0 "register_operand" "=&d")
        (ashift:DI (match_operand:DI 1 "register_operand" "d")
                   (match_operand:SI 2 "register_operand" "d")))
    (clobber (match_operand:SI 3 "register_operand" "=d"))]
@@ -2317,7 +2367,7 @@ move\\t%0,%z4\\n\\
 
 
 (define_insn "ashrdi3_internal"
-  [(set (match_operand:DI 0 "register_operand" "=d")
+  [(set (match_operand:DI 0 "register_operand" "=&d")
        (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
                     (match_operand:SI 2 "register_operand" "d")))
    (clobber (match_operand:SI 3 "register_operand" "=d"))]
@@ -3843,14 +3893,22 @@ move\\t%0,%z4\\n\\
 ;; Function return, only allow after optimization, so that we can
 ;; eliminate jumps to jumps if no stack space is used.
 
-(define_insn "return"
-  [(return)]
-  "null_epilogue ()"
-  "*
-{
-  operands[0] = gen_rtx (REG, SImode, GP_REG_FIRST + 31);
-  return \"%*j\\t%0\";
-}"
+;; (define_expand "return"
+;;   [(set (pc) (reg:SI 31))]
+;;   "simple_epilogue_p ()"
+;;   "")
+
+(define_expand "return"
+  [(parallel [(return)
+             (use (reg:SI 31))])]
+  "simple_epilogue_p ()"
+  "")
+
+(define_insn "return_internal"
+  [(parallel [(return)
+              (use (match_operand:SI 0 "register_operand" "d"))])]
+  ""
+  "%*j\\t%0"
   [(set_attr "type"    "jump")
    (set_attr "mode"    "none")
    (set_attr "length"  "1")])
@@ -3859,6 +3917,42 @@ move\\t%0,%z4\\n\\
 ;;
 ;;  ....................
 ;;
+;;     Function prologue/epilogue
+;;
+;;  ....................
+;;
+
+(define_expand "prologue"
+  [(const_int 1)]
+  ""
+  "
+{
+  if (mips_isa >= 0)           /* avoid unused code warnings */
+    {
+      mips_expand_prologue ();
+      DONE;
+    }
+}")
+
+;; At present, don't expand the epilogue, reorg.c will clobber the
+;; return register in compiling gen_lowpart (emit-rtl.c).
+;; 
+;; (define_expand "epilogue"
+;;   [(const_int 2)]
+;;   ""
+;;   "
+;; {
+;;   if (mips_isa >= 0)            /* avoid unused code warnings */
+;;     {
+;;       mips_expand_epilogue ();
+;;       DONE;
+;;     }
+;; }")
+
+\f
+;;
+;;  ....................
+;;
 ;;     FUNCTION CALLS
 ;;
 ;;  ....................