* config/tc-mips.c (md_section_align): Do align if OBJ_ELF, but
[binutils-gdb.git] / gas / config / tc-mips.c
index 1f7f951d3ed4792df2ada680d856eb60cd0ac298..38bcebc5dc467f66c9d8d9e87c013d778e180b3d 100644 (file)
@@ -70,7 +70,9 @@ static int mips_output_flavor () { return OUTPUT_FLAVOR; }
 
 #include "ecoff.h"
 
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
 static char *mips_regmask_frag;
+#endif
 
 #define AT  1
 #define PIC_CALL_REG 25
@@ -1007,8 +1009,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
       /* The previous insn might require a delay slot, depending upon
         the contents of the current insn.  */
       if (mips_isa < 4
-         && ((prev_pinfo & INSN_LOAD_COPROC_DELAY)
-              && ! cop_interlocks
+         && (((prev_pinfo & INSN_LOAD_COPROC_DELAY)
+               && ! cop_interlocks)
              || (mips_isa < 2
                  && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))))
        {
@@ -1025,8 +1027,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
            ++nops;
        }
       else if (mips_isa < 4
-              && ((prev_pinfo & INSN_COPROC_MOVE_DELAY)
-                   && ! cop_interlocks
+              && (((prev_pinfo & INSN_COPROC_MOVE_DELAY)
+                    && ! cop_interlocks)
                   || (mips_isa < 2
                       && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))))
        {
@@ -1147,10 +1149,16 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
       /* Now emit the right number of NOP instructions.  */
       if (nops > 0)
        {
+         fragS *old_frag;
+         unsigned long old_frag_offset;
          int i;
 
+         old_frag = frag_now;
+         old_frag_offset = frag_now_fix ();
+
          for (i = 0; i < nops; i++)
            emit_nop ();
+
          if (listing)
            {
              listing_prev_line ();
@@ -1164,12 +1172,18 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
                  all needed nop instructions themselves.  */
              frag_grow (40);
            }
+
          if (insn_label != NULL)
            {
              assert (S_GET_SEGMENT (insn_label) == now_seg);
              insn_label->sy_frag = frag_now;
              S_SET_VALUE (insn_label, (valueT) frag_now_fix ());
            }
+
+#ifndef NO_ECOFF_DEBUGGING
+         if (ECOFF_DEBUGGING)
+           ecoff_fix_loc (old_frag, old_frag_offset);
+#endif
        }
     }
   
@@ -1442,7 +1456,6 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
        }
       else if (pinfo & INSN_COND_BRANCH_LIKELY)
        {
-printf("DBG: append_insn: inserting a NOP (INSN_COND_BRANCH_LIKELY)\n");
          /* We don't yet optimize a branch likely.  What we should do
             is look at the target, copy the instruction found there
             into the delay slot, and increment the branch to jump to
@@ -5615,8 +5628,9 @@ mips_ip (str, ip)
              if (*args == 'i')
                {
                  if ((c == '\0' && imm_expr.X_op != O_constant)
-                     || imm_expr.X_add_number < 0
-                     || imm_expr.X_add_number >= 0x10000)
+                     || ((imm_expr.X_add_number < 0
+                           || imm_expr.X_add_number >= 0x10000)
+                          && imm_expr.X_op == O_constant))
                    {
                      if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
                          !strcmp (insn->name, insn[1].name))
@@ -5649,8 +5663,9 @@ mips_ip (str, ip)
                  else
                    max = 0x10000;
                  if ((c == '\0' && imm_expr.X_op != O_constant)
-                     || imm_expr.X_add_number < -0x8000
-                     || imm_expr.X_add_number >= max
+                     || ((imm_expr.X_add_number < -0x8000
+                           || imm_expr.X_add_number >= max)
+                          && imm_expr.X_op == O_constant)
                      || (more
                          && imm_expr.X_add_number < 0
                          && mips_isa >= 3
@@ -7380,6 +7395,14 @@ md_section_align (seg, addr)
 {
   int align = bfd_get_section_alignment (stdoutput, seg);
 
+#ifdef OBJ_ELF
+  /* We don't need to align ELF sections to the full alignment.
+     However, Irix 5 may prefer that we align them at least to a 16
+     byte boundary.  */
+  if (align > 16)
+    align = 16;
+#endif
+
   return ((addr + (1 << align) - 1) & (-1 << align));
 }
 
@@ -7501,6 +7524,7 @@ tc_gen_reloc (section, fixp)
 {
   static arelent *retval[4];
   arelent *reloc;
+  bfd_reloc_code_real_type code;
 
   reloc = retval[0] = (arelent *) xmalloc (sizeof (arelent));
   retval[1] = NULL;
@@ -7633,20 +7657,53 @@ tc_gen_reloc (section, fixp)
        abort ();
     }
 
+  /* Since DIFF_EXPR_OK is defined in tc-mips.h, it is possible that
+     fixup_segment converted a non-PC relative reloc into a PC
+     relative reloc.  In such a case, we need to convert the reloc
+     code.  */
+  code = fixp->fx_r_type;
+  if (fixp->fx_pcrel)
+    {
+      switch (code)
+       {
+       case BFD_RELOC_8:
+         code = BFD_RELOC_8_PCREL;
+         break;
+       case BFD_RELOC_16:
+         code = BFD_RELOC_16_PCREL;
+         break;
+       case BFD_RELOC_32:
+         code = BFD_RELOC_32_PCREL;
+         break;
+       case BFD_RELOC_8_PCREL:
+       case BFD_RELOC_16_PCREL:
+       case BFD_RELOC_32_PCREL:
+       case BFD_RELOC_16_PCREL_S2:
+       case BFD_RELOC_PCREL_HI16_S:
+       case BFD_RELOC_PCREL_LO16:
+         break;
+       default:
+         as_bad_where (fixp->fx_file, fixp->fx_line,
+                       "Cannot make %s relocation PC relative",
+                       bfd_get_reloc_code_name (code));
+       }
+    }
+
   /* To support a PC relative reloc when generating embedded PIC code
      for ECOFF, we use a Cygnus extension.  We check for that here to
      make sure that we don't let such a reloc escape normally.  */
   if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
-      && fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
+      && code == BFD_RELOC_16_PCREL_S2
       && mips_pic != EMBEDDED_PIC)
     reloc->howto = NULL;
   else
-    reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+    reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
 
   if (reloc->howto == NULL)
     {
       as_bad_where (fixp->fx_file, fixp->fx_line,
-                   "Can not represent relocation in this object file format");
+                   "Can not represent %s relocation in this object file format",
+                   bfd_get_reloc_code_name (code));
       retval[0] = NULL;
     }