2001-04-07 Steven J. Hill <sjhill@cotw.com>
[deliverable/binutils-gdb.git] / gas / config / tc-mips.c
index c6e98912f13b34a4650e55225c0faa84f7d78e48..6c2f3173140f883ecc8e5b851a19468b79c9f147 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-mips.c -- assemble code for a MIPS chip.
-   Copyright (C) 1993, 94, 95, 96, 97, 98, 1999, 2000
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
    Contributed by the OSF and Ralph Campbell.
    Written by Keith Knowles and Ralph Campbell, working independently.
@@ -126,7 +126,8 @@ mips_target_format ()
 #ifdef TE_TMIPS
       /* This is traditional mips */
       return (target_big_endian
-             ? "elf32-tradbigmips" : "elf32-tradlittlemips");
+             ? (mips_64 ? "elf64-tradbigmips" : "elf32-tradbigmips")
+             : (mips_64 ? "elf64-tradlittlemips" : "elf32-tradlittlemips"));
 #else
       return (target_big_endian
              ? (mips_64 ? "elf64-bigmips" : "elf32-bigmips")
@@ -153,7 +154,8 @@ mips_target_format ()
    pseudo-op.  We use a struct so that .set push and .set pop are more
    reliable.  */
 
-struct mips_set_options {
+struct mips_set_options
+{
   /* MIPS ISA (Instruction Set Architecture) level.  This is set to -1
      if it has not been initialized.  Changed by `.set mipsN', and the
      -mipsN command line option, and the default CPU.  */
@@ -190,7 +192,8 @@ struct mips_set_options {
    that we must set the isa field to ISA_UNKNOWN and the mips16 field to
    -1 to indicate that they have not been initialized.  */
 
-static struct mips_set_options mips_opts = {
+static struct mips_set_options mips_opts =
+{
   ISA_UNKNOWN, -1, 0, 0, 0, 0, 0, 0
 };
 
@@ -207,7 +210,7 @@ static int file_mips_isa = ISA_UNKNOWN;
 static int mips_cpu = CPU_UNKNOWN;
 
 /* The argument of the -mabi= flag.  */
-static char *mips_abi_string = 0;
+static char * mips_abi_string = 0;
 
 /* Wether we should mark the file EABI64 or EABI32.  */
 static int mips_eabi64 = 0;
@@ -289,7 +292,8 @@ static int mips_gp32 = 0;
 
 /* MIPS PIC level.  */
 
-enum mips_pic_level {
+enum mips_pic_level
+{
   /* Do not generate PIC code.  */
   NO_PIC,
 
@@ -483,7 +487,8 @@ static int prev_nop_frag_since;
    relocation.  We then sort them so that they immediately precede the
    corresponding LO relocation.  */
 
-struct mips_hi_fixup {
+struct mips_hi_fixup
+{
   /* Next HI fixup.  */
   struct mips_hi_fixup *next;
   /* This fixup.  */
@@ -499,7 +504,8 @@ static struct mips_hi_fixup *mips_hi_fixup_list;
 /* Map normal MIPS register numbers to mips16 register numbers.  */
 
 #define X ILLEGAL_REG
-static const int mips32_to_16_reg_map[] = {
+static const int mips32_to_16_reg_map[] =
+{
   X, X, 2, 3, 4, 5, 6, 7,
   X, X, X, X, X, X, X, X,
   0, 1, X, X, X, X, X, X,
@@ -509,7 +515,8 @@ static const int mips32_to_16_reg_map[] = {
 
 /* Map mips16 register numbers to normal MIPS register numbers.  */
 
-static const unsigned int mips16_to_32_reg_map[] = {
+static const unsigned int mips16_to_32_reg_map[] =
+{
   16, 17, 2, 3, 4, 5, 6, 7
 };
 \f
@@ -713,7 +720,8 @@ static int validate_mips_insn PARAMS ((const struct mips_opcode *));
 /* Table and functions used to map between CPU/ISA names, and
    ISA levels, and CPU numbers.  */
 
-struct mips_cpu_info {
+struct mips_cpu_info
+{
   const char *name;           /* CPU or ISA name.  */
   int is_isa;                 /* Is this an ISA?  (If 0, a CPU.) */
   int isa;                    /* ISA level.  */
@@ -742,7 +750,8 @@ static const struct mips_cpu_info *mips_cpu_info_from_cpu PARAMS ((int));
    they are not currently supported: .asm0, .endr, .lab, .repeat,
    .struct.  */
 
-static const pseudo_typeS mips_pseudo_table[] = {
+static const pseudo_typeS mips_pseudo_table[] =
+{
   /* MIPS specific pseudo-ops.  */
   {"option", s_option, 0},
   {"set", s_mipsset, 0},
@@ -787,7 +796,8 @@ static const pseudo_typeS mips_pseudo_table[] = {
   { NULL, NULL, 0 },
 };
 
-static const pseudo_typeS mips_nonecoff_pseudo_table[] = {
+static const pseudo_typeS mips_nonecoff_pseudo_table[] =
+{
   /* These pseudo-ops should be defined by the object file format.
      However, a.out doesn't support them, so we have versions here.  */
   {"aent", s_mips_ent, 1},
@@ -816,7 +826,8 @@ mips_pop_insert ()
 \f
 /* Symbols labelling the current insn.  */
 
-struct insn_label_list {
+struct insn_label_list
+{
   struct insn_label_list *next;
   symbolS *label;
 };
@@ -1543,7 +1554,6 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
               && insn_uses_reg (ip, ((prev_insn.insn_opcode >> OP_SH_RD)
                                      & OP_MASK_RD),
                                 MIPS_GR_REG))
-
        {
          nops += 2;
        }
@@ -3927,7 +3937,7 @@ macro (ip)
          if (mips_trap)
            macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);
          else
-             macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+           macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
          return;
        }
 
@@ -3948,7 +3958,7 @@ macro (ip)
          macro_build ((char *) NULL, &icnt, NULL,
                       dbl ? "ddiv" : "div",
                       "z,s,t", sreg, treg);
-           macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+         macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
        }
       expr1.X_add_number = -1;
       macro_build ((char *) NULL, &icnt, &expr1,
@@ -3987,7 +3997,7 @@ macro (ip)
             that later insns are available for delay slot filling.  */
          --mips_opts.noreorder;
 
-           macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+         macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
        }
       macro_build ((char *) NULL, &icnt, NULL, s, "d", dreg);
       break;
@@ -4204,9 +4214,13 @@ macro (ip)
        }
       else if (mips_pic == SVR4_PIC && ! mips_big_got)
        {
+         int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
+
          /* If this is a reference to an external symbol, and there
             is no constant, we want
               lw       $tempreg,<sym>($gp)     (BFD_RELOC_MIPS_GOT16)
+            or if tempreg is PIC_CALL_REG
+              lw       $tempreg,<sym>($gp)     (BFD_RELOC_MIPS_CALL16)
             For a local symbol, we want
               lw       $tempreg,<sym>($gp)     (BFD_RELOC_MIPS_GOT16)
               nop
@@ -4233,9 +4247,11 @@ macro (ip)
          expr1.X_add_number = offset_expr.X_add_number;
          offset_expr.X_add_number = 0;
          frag_grow (32);
+         if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
+           lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       dbl ? "ld" : "lw",
-                      "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
+                      "t,o(b)", tempreg, lw_reloc_type, GP);
          if (expr1.X_add_number == 0)
            {
              int off;
@@ -4341,12 +4357,18 @@ macro (ip)
       else if (mips_pic == SVR4_PIC)
        {
          int gpdel;
+         int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
+         int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
 
          /* This is the large GOT case.  If this is a reference to an
             external symbol, and there is no constant, we want
               lui      $tempreg,<sym>          (BFD_RELOC_MIPS_GOT_HI16)
               addu     $tempreg,$tempreg,$gp
               lw       $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+            or if tempreg is PIC_CALL_REG
+              lui      $tempreg,<sym>          (BFD_RELOC_MIPS_CALL_HI16)
+              addu     $tempreg,$tempreg,$gp
+              lw       $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_CALL_LO16)
             For a local symbol, we want
               lw       $tempreg,<sym>($gp)     (BFD_RELOC_MIPS_GOT16)
               nop
@@ -4385,8 +4407,13 @@ macro (ip)
            gpdel = 4;
          else
            gpdel = 0;
+         if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
+           {
+             lui_reloc_type = (int) BFD_RELOC_MIPS_CALL_HI16;
+             lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
+           }
          macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
-                      tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
+                      tempreg, lui_reloc_type);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
                         || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
@@ -4394,8 +4421,7 @@ macro (ip)
                       "d,v,t", tempreg, tempreg, GP);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       dbl ? "ld" : "lw",
-                      "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT_LO16,
-                      tempreg);
+                      "t,o(b)", tempreg, lw_reloc_type, tempreg);
          if (expr1.X_add_number == 0)
            {
              int off;
@@ -6912,7 +6938,7 @@ validate_mips_insn (opc)
       case 'G':        USE_BITS (OP_MASK_RD,           OP_SH_RD);      break;
       case 'H': USE_BITS (OP_MASK_SEL,         OP_SH_SEL);     break;
       case 'I': break;
-      case 'J':       USE_BITS (OP_MASK_CODE19,       OP_SH_CODE19);  break;
+      case 'J': USE_BITS (OP_MASK_CODE19,       OP_SH_CODE19);  break;
       case 'L': break;
       case 'M':        USE_BITS (OP_MASK_CCC,          OP_SH_CCC);     break;
       case 'N':        USE_BITS (OP_MASK_BCC,          OP_SH_BCC);     break;
@@ -8461,7 +8487,8 @@ mips16_ip (str, ip)
 /* This structure holds information we know about a mips16 immediate
    argument type.  */
 
-struct mips16_immed_operand {
+struct mips16_immed_operand
+{
   /* The type code used in the argument string in the opcode table.  */
   int type;
   /* The number of bits in the short form of the opcode.  */
@@ -8819,7 +8846,8 @@ md_number_to_chars (buf, val, n)
 \f
 CONST char *md_shortopts = "O::g::G:";
 
-struct option md_longopts[] = {
+struct option md_longopts[] =
+{
 #define OPTION_MIPS1 (OPTION_MD_BASE + 1)
   {"mips0", no_argument, NULL, OPTION_MIPS1},
   {"mips1", no_argument, NULL, OPTION_MIPS1},
@@ -9046,6 +9074,7 @@ md_parse_option (c, arg)
       g_switch_value = 0x7fffffff;
       break;
 
+#ifdef OBJ_ELF
       /* When generating ELF code, we permit -KPIC and -call_shared to
         select SVR4_PIC, and -non_shared to select no PIC.  This is
         intended to be compatible with Irix 5.  */
@@ -9079,6 +9108,7 @@ md_parse_option (c, arg)
     case OPTION_XGOT:
       mips_big_got = 1;
       break;
+#endif /* OBJ_ELF */
 
     case 'G':
       if (! USE_GLOBAL_POINTER_OPT)
@@ -9096,6 +9126,7 @@ md_parse_option (c, arg)
       g_switch_seen = 1;
       break;
 
+#ifdef OBJ_ELF
       /* The -32 and -64 options tell the assembler to output the 32
          bit or the 64 bit MIPS ELF format.  */
     case OPTION_32:
@@ -9117,6 +9148,7 @@ md_parse_option (c, arg)
        mips_64 = 1;
       }
       break;
+#endif /* OBJ_ELF */
 
     case OPTION_GP32:
       mips_gp32 = 1;
@@ -10158,7 +10190,8 @@ s_option (x)
 
 /* This structure is used to hold a stack of .set values.  */
 
-struct mips_option_stack {
+struct mips_option_stack
+{
   struct mips_option_stack *next;
   struct mips_set_options options;
 };
@@ -11321,7 +11354,7 @@ md_convert_frag (abfd, asec, fragp)
          ext = false;
        }
 
-      resolve_symbol_value (fragp->fr_symbol, 1);
+      resolve_symbol_value (fragp->fr_symbol, finalize_syms);
       val = S_GET_VALUE (fragp->fr_symbol);
       if (op->pcrel)
        {
@@ -11538,34 +11571,37 @@ static procS cur_proc;
 static procS *cur_proc_ptr;
 static int numprocs;
 
-/* When we align code in the .text section of mips16, use the correct two
-   byte nop pattern of 0x6500 (move $0,$0) */
+/* Fill in an rs_align_code fragment.  */
 
-int
-mips_do_align (n, fill, len, max)
-     int n;
-     const char *fill;
-     int len ATTRIBUTE_UNUSED;
-     int max;
+void
+mips_handle_align (fragp)
+     fragS *fragp;
 {
-  if (fill == NULL
-      && subseg_text_p (now_seg)
-      && n > 1
-      && mips_opts.mips16)
+  if (fragp->fr_type != rs_align_code)
+    return;
+
+  if (mips_opts.mips16)
     {
       static const unsigned char be_nop[] = { 0x65, 0x00 };
       static const unsigned char le_nop[] = { 0x00, 0x65 };
 
-      frag_align (1, 0, 0);
+      int bytes;
+      char *p;
 
-      if (target_big_endian)
-       frag_align_pattern (n, be_nop, 2, max);
-      else
-       frag_align_pattern (n, le_nop, 2, max);
-      return 1;
+      bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
+      p = fragp->fr_literal + fragp->fr_fix;
+
+      if (bytes & 1)
+       {
+         *p++ = 0;
+         fragp->fr_fix += 1;
+       }
+
+      memcpy (p, (target_big_endian ? be_nop : le_nop), 2);
+      fragp->fr_var = 2;
     }
 
-  return 0;
+  /* For mips32, a nop is a zero, which we trivially get by doing nothing.  */
 }
 
 static void
@@ -11908,7 +11944,8 @@ s_loc (x)
 
    Case is ignored in comparison, so put the canonical entry in the
    appropriate case but everything else in lower case to ease eye pain.  */
-static const struct mips_cpu_info mips_cpu_info_table[] = {
+static const struct mips_cpu_info mips_cpu_info_table[] =
+{
   /* MIPS1 ISA */
   { "MIPS1",          1,      ISA_MIPS1,      CPU_R3000, },
   { "mips",           1,      ISA_MIPS1,      CPU_R3000, },
@@ -11955,7 +11992,7 @@ static const struct mips_cpu_info mips_cpu_info_table[] = {
   /* TX3900 CPU */
   { "R3900",          0,      ISA_MIPS1,      CPU_R3900, },
   { "3900",           0,      ISA_MIPS1,      CPU_R3900, },
-  { "mipstx39",               0,      ISA_MIPS1,      CPU_R3900, },
+  { "mipstx39",       0,      ISA_MIPS1,      CPU_R3900, },
 
   /* R4000 CPU */
   { "R4000",          0,      ISA_MIPS3,      CPU_R4000, },
@@ -12042,7 +12079,7 @@ static const struct mips_cpu_info mips_cpu_info_table[] = {
 
   /* SiByte SB-1 CPU */
   { "SB-1",           0,      ISA_MIPS64,     CPU_SB1, },
-  { "sb-1250",                0,      ISA_MIPS64,     CPU_SB1, },
+  { "sb-1250",        0,      ISA_MIPS64,     CPU_SB1, },
   { "sb1",            0,      ISA_MIPS64,     CPU_SB1, },
   { "sb1250",         0,      ISA_MIPS64,     CPU_SB1, },
 
@@ -12060,7 +12097,7 @@ mips_cpu_info_from_name (name)
     if (strcasecmp (name, mips_cpu_info_table[i].name) == 0)
       return (&mips_cpu_info_table[i]);
 
-  return (NULL);
+  return NULL;
 }
 
 static const struct mips_cpu_info *
@@ -12074,7 +12111,7 @@ mips_cpu_info_from_isa (isa)
       && isa == mips_cpu_info_table[i].isa)
       return (&mips_cpu_info_table[i]);
 
-  return (NULL);
+  return NULL;
 }
 
 static const struct mips_cpu_info *
@@ -12088,5 +12125,5 @@ mips_cpu_info_from_cpu (cpu)
       && cpu == mips_cpu_info_table[i].cpu)
       return (&mips_cpu_info_table[i]);
 
-  return (NULL);
+  return NULL;
 }
This page took 0.033771 seconds and 4 git commands to generate.