Removed generation of the PT_GNU_PROPERTY segment
[external/binutils.git] / gas / config / tc-msp430.c
index d4b2407..5821b1c 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-msp430.c -- Assembler code for the Texas Instruments MSP430
 
-  Copyright (C) 2002-2018 Free Software Foundation, Inc.
+  Copyright (C) 2002-2019 Free Software Foundation, Inc.
   Contributed by Dmitry Diky <diwil@mail.ru>
 
   This file is part of GAS, the GNU Assembler.
@@ -209,9 +209,9 @@ static struct hash_control *msp430_hash;
 #define CEBL   4
 
 /* Length.  */
-#define STATE_BITS10   1       /* wild guess. short jump */
-#define STATE_WORD     2       /* 2 bytes pc rel. addr. more */
-#define STATE_UNDEF    3       /* cannot handle this yet. convert to word mode */
+#define STATE_BITS10   1       /* Wild guess. short jump.  */
+#define STATE_WORD     2       /* 2 bytes pc rel. addr. more */
+#define STATE_UNDEF    3       /* Cannot handle this yet. convert to word mode.  */
 
 #define ENCODE_RELAX(what,length) (((what) << 2) + (length))
 #define RELAX_STATE(s)            ((s) & 3)
@@ -415,6 +415,7 @@ parse_exp (char * s, expressionS * op)
   expression (op);
   if (op->X_op == O_absent)
     as_bad (_("missing operand"));
+
   /* Our caller is likely to check that the entire expression was parsed.
      If we have found a hex constant with an 'h' suffix, ilp will be left
      pointing at the 'h', so skip it here.  */
@@ -680,6 +681,9 @@ static bfd_boolean gen_interrupt_nops = FALSE;
 #define OPTION_WARN_INTR_NOPS 'y'
 #define OPTION_NO_WARN_INTR_NOPS 'Y'
 static bfd_boolean warn_interrupt_nops = TRUE;
+#define OPTION_UNKNOWN_INTR_NOPS 'u'
+#define OPTION_NO_UNKNOWN_INTR_NOPS 'U'
+static bfd_boolean do_unknown_interrupt_nops = TRUE;
 #define OPTION_MCPU 'c'
 #define OPTION_MOVE_DATA 'd'
 static bfd_boolean move_data = FALSE;
@@ -1454,6 +1458,13 @@ md_parse_option (int c, const char * arg)
       warn_interrupt_nops = FALSE;
       return 1;
 
+    case OPTION_UNKNOWN_INTR_NOPS:
+      do_unknown_interrupt_nops = TRUE;
+      return 1;
+    case OPTION_NO_UNKNOWN_INTR_NOPS:
+      do_unknown_interrupt_nops = FALSE;
+      return 1;
+
     case OPTION_MOVE_DATA:
       move_data = TRUE;
       return 1;
@@ -1484,13 +1495,16 @@ static void
 msp430_make_init_symbols (const char * name)
 {
   if (strncmp (name, ".bss", 4) == 0
+      || strncmp (name, ".lower.bss", 10) == 0
+      || strncmp (name, ".either.bss", 11) == 0
       || strncmp (name, ".gnu.linkonce.b.", 16) == 0)
     (void) symbol_find_or_make ("__crt0_init_bss");
 
   if (strncmp (name, ".data", 5) == 0
+      || strncmp (name, ".lower.data", 11) == 0
+      || strncmp (name, ".either.data", 12) == 0
       || strncmp (name, ".gnu.linkonce.d.", 16) == 0)
     (void) symbol_find_or_make ("__crt0_movedata");
-
   /* Note - data assigned to the .either.data section may end up being
      placed in the .upper.data section if the .lower.data section is
      full.  Hence the need to define the crt0 symbol.
@@ -1507,6 +1521,32 @@ msp430_make_init_symbols (const char * name)
       || strncmp (name, ".either.bss", 11) == 0
       || upper_data_region_in_use)
     (void) symbol_find_or_make ("__crt0_init_highbss");
+
+  /* The following symbols are for the crt0 functions that run through
+     the different .*_array sections and call the functions placed there.
+     - init_array stores global static C++ constructors to run before main.
+     - preinit_array is not expected to ever be used for MSP430.
+     GCC only places initialization functions for runtime "sanitizers"
+     (i.e. {a,l,t,u}san) and "virtual table verification" in preinit_array.
+     - fini_array stores global static C++ destructors to run after calling
+     exit() or returning from main.
+     __crt0_run_array is required to actually call the functions in the above
+     arrays.  */
+  if (strncmp (name, ".init_array", 11) == 0)
+    {
+      (void) symbol_find_or_make ("__crt0_run_init_array");
+      (void) symbol_find_or_make ("__crt0_run_array");
+    }
+  else if (strncmp (name, ".preinit_array", 14) == 0)
+    {
+      (void) symbol_find_or_make ("__crt0_run_preinit_array");
+      (void) symbol_find_or_make ("__crt0_run_array");
+    }
+  else if (strncmp (name, ".fini_array", 11) == 0)
+    {
+      (void) symbol_find_or_make ("__crt0_run_fini_array");
+      (void) symbol_find_or_make ("__crt0_run_array");
+    }
 }
 
 static void
@@ -1574,7 +1614,7 @@ const pseudo_typeS md_pseudo_table[] =
   {NULL, NULL, 0}
 };
 
-const char *md_shortopts = "mm:,mP,mQ,ml,mN,mn,my,mY";
+const char *md_shortopts = "mm:,mP,mQ,ml,mN,mn,my,mY,mu,mU";
 
 struct option md_longopts[] =
 {
@@ -1589,6 +1629,8 @@ struct option md_longopts[] =
   {"mn", no_argument, NULL, OPTION_INTR_NOPS},
   {"mY", no_argument, NULL, OPTION_NO_WARN_INTR_NOPS},
   {"my", no_argument, NULL, OPTION_WARN_INTR_NOPS},
+  {"mu", no_argument, NULL, OPTION_UNKNOWN_INTR_NOPS},
+  {"mU", no_argument, NULL, OPTION_NO_UNKNOWN_INTR_NOPS},
   {"md", no_argument, NULL, OPTION_MOVE_DATA},
   {"mdata-region", required_argument, NULL, OPTION_DATA_REGION},
   {NULL, no_argument, NULL, 0}
@@ -1621,6 +1663,13 @@ md_show_usage (FILE * stream)
   fprintf (stream,
           _("  -my - warn about missing NOPs after changing interrupts (default)\n"));
   fprintf (stream,
+          _("  -mU - for an instruction which changes interrupt state, but where it is not\n"
+            "        known how the state is changed, do not warn/insert NOPs\n"));
+  fprintf (stream,
+          _("  -mu - for an instruction which changes interrupt state, but where it is not\n"
+            "        known how the state is changed, warn/insert NOPs (default)\n"
+            "        -mn and/or -my are required for this to have any effect\n"));
+  fprintf (stream,
           _("  -md - Force copying of data from ROM to RAM at startup\n"));
   fprintf (stream,
           _("  -mdata-region={none|lower|upper|either} - select region data will be\n"
@@ -1981,8 +2030,8 @@ msp430_srcoperand (struct msp430_operand_s * op,
     {
       char *h = l;
 
-      op->reg = 2;             /* reg 2 in absolute addr mode.  */
-      op->am = 1;              /* mode As == 01 bin.  */
+      op->reg = 2;             /* Reg 2 in absolute addr mode.  */
+      op->am = 1;              /* Mode As == 01 bin.  */
       op->ol = 1;              /* Immediate value followed by instruction.  */
       __tl = h + 1;
       end = parse_exp (__tl, &(op->exp));
@@ -2532,15 +2581,18 @@ gen_nop (void)
 }
 
 /* Insert/inform about adding a NOP if this insn enables interrupts.  */
+
 static void
 warn_eint_nop (bfd_boolean prev_insn_is_nop, bfd_boolean prev_insn_is_dint)
 {
   if (prev_insn_is_nop
-      /* Prevent double warning for DINT immediately before EINT.  */
+      /* If the last insn was a DINT, we will have already warned that a NOP is
+        required after it.  */
       || prev_insn_is_dint
       /* 430 ISA does not require a NOP before EINT.  */
       || (! target_is_430x ()))
     return;
+
   if (gen_interrupt_nops)
     {
       gen_nop ();
@@ -2553,11 +2605,19 @@ warn_eint_nop (bfd_boolean prev_insn_is_nop, bfd_boolean prev_insn_is_dint)
 
 /* Use when unsure what effect the insn will have on the interrupt status,
    to insert/warn about adding a NOP before the current insn.  */
+
 static void
-warn_unsure_interrupt (void)
+warn_unsure_interrupt (bfd_boolean prev_insn_is_nop,
+                      bfd_boolean prev_insn_is_dint)
 {
-  /* Since this could enable or disable interrupts, need to add/warn about
-     adding a NOP before and after this insn.  */
+  if (prev_insn_is_nop
+      /* If the last insn was a DINT, we will have already warned that a NOP is
+        required after it.  */
+      || prev_insn_is_dint
+      /* 430 ISA does not require a NOP before EINT or DINT.  */
+      || (! target_is_430x ()))
+    return;
+
   if (gen_interrupt_nops)
     {
       gen_nop ();
@@ -2827,7 +2887,8 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
 
   switch (fmt)
     {
-    case 0:                    /* Emulated.  */
+    case 0:
+      /* Emulated.  */
       switch (opcode->insn_opnumb)
        {
        case 0:
@@ -3646,12 +3707,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          else if (op1.mode == OP_REG
                   && (op1.reg == 2 || op1.reg == 3))
            this_insn_is_dint = TRUE;
-         else
+         else if (do_unknown_interrupt_nops)
            {
              /* FIXME: Couldn't work out whether the insn is enabling or
                 disabling interrupts, so for safety need to treat it as both
                 a DINT and EINT.  */
-             warn_unsure_interrupt ();
+             warn_unsure_interrupt (prev_insn_is_nop, prev_insn_is_dint);
              check_for_nop |= NOP_CHECK_INTERRUPT;
            }
        }