]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add support for MSP430 silicon errata to the assembler.
authorNick Clifton <nickc@redhat.com>
Thu, 22 Oct 2015 15:25:46 +0000 (16:25 +0100)
committerNick Clifton <nickc@redhat.com>
Thu, 22 Oct 2015 15:25:46 +0000 (16:25 +0100)
* config/tc-msp430.c (PUSH_1X_WORKAROUND): Delete.
(OPTION_SILICON_ERRATA): Define.
(OPTION_SILICON_WARN): Define.
(md_parse_opton): Handle silicon errata options.
(md_longopts): Add silicon errata options.
(ms_show_usage): Report silicon errata options.
(msp430_srcoperand): Handle silicon errata.
(msp430_operands): Likewise. Improve nop insertion.
(msp430_fix_adjustable): Update warning generation.
* doc/c-msp430.texi: Document silicon errata options.

tests * gas/msp430/errata_fixes.s: New test source file.
* gas/msp430/errata_fixes.d: New test control file.
* gas/msp430/errata_warns.s: New test source file.
* gas/msp430/errata_warns.d: New test control file.
* gas/msp430/errata_warns.l: New test message file.
* gas/msp430/msp430.exp: Run the new tests.
* gas/msp430/bad.l: Update expected warning messages
* gas/msp430/msp430.exp: Run the new tests.

gas/ChangeLog
gas/config/tc-msp430.c
gas/doc/c-msp430.texi
gas/testsuite/ChangeLog
gas/testsuite/gas/msp430/bad.l
gas/testsuite/gas/msp430/errata_fixes.d [new file with mode: 0644]
gas/testsuite/gas/msp430/errata_fixes.s [new file with mode: 0644]
gas/testsuite/gas/msp430/errata_warns.d [new file with mode: 0644]
gas/testsuite/gas/msp430/errata_warns.l [new file with mode: 0644]
gas/testsuite/gas/msp430/errata_warns.s [new file with mode: 0644]
gas/testsuite/gas/msp430/msp430.exp

index 0743ff30ee015a2de0a019330fceb2dcf863431e..1b77b64ba015aafbdd27928a7426972604ed777e 100644 (file)
@@ -1,3 +1,16 @@
+2015-10-22  Nick Clifton  <nickc@redhat.com>
+
+       * config/tc-msp430.c (PUSH_1X_WORKAROUND): Delete.
+       (OPTION_SILICON_ERRATA): Define.
+       (OPTION_SILICON_WARN): Define.
+       (md_parse_opton): Handle silicon errata options.
+       (md_longopts): Add silicon errata options.
+       (ms_show_usage): Report silicon errata options.
+       (msp430_srcoperand): Handle silicon errata.
+       (msp430_operands): Likewise. Improve nop insertion.
+       (msp430_fix_adjustable): Update warning generation.
+       * doc/c-msp430.texi: Document silicon errata options.
+
 2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
 
        * configure.ac: Properly check
index accc5923c8ee437c68b0b8c841df974a432b1cbc..8e32189ef8e0a1574a38915becc9213339a3cc65 100644 (file)
@@ -22,7 +22,6 @@
 
 #include "as.h"
 #include <limits.h>
-#define PUSH_1X_WORKAROUND
 #include "subsegs.h"
 #include "opcode/msp430.h"
 #include "safe-ctype.h"
@@ -681,6 +680,23 @@ static bfd_boolean warn_interrupt_nops = TRUE;
 #define OPTION_MOVE_DATA 'd'
 static bfd_boolean move_data = FALSE;
 
+enum
+{
+  OPTION_SILICON_ERRATA = OPTION_MD_BASE,
+  OPTION_SILICON_ERRATA_WARN,
+} option_numbers;
+
+static unsigned int silicon_errata_fix = 0;
+static unsigned int silicon_errata_warn = 0;
+#define SILICON_ERRATA_CPU4            (1 << 0)
+#define SILICON_ERRATA_CPU8            (1 << 1)
+#define SILICON_ERRATA_CPU11           (1 << 2)
+#define SILICON_ERRATA_CPU12           (1 << 3)
+#define SILICON_ERRATA_CPU13           (1 << 4)
+#define SILICON_ERRATA_CPU19           (1 << 5)
+#define SILICON_ERRATA_CPU42           (1 << 6)
+#define SILICON_ERRATA_CPU42_PLUS      (1 << 7)
+
 static void
 msp430_set_arch (int option)
 {
@@ -1305,6 +1321,55 @@ md_parse_option (int c, char * arg)
 {
   switch (c)
     {
+    case OPTION_SILICON_ERRATA:
+    case OPTION_SILICON_ERRATA_WARN:
+      {
+       signed int i;
+       const struct
+       {
+         char *       name;
+         unsigned int length;
+         unsigned int bitfield;
+       } erratas[] =
+       {
+         { STRING_COMMA_LEN ("cpu4"), SILICON_ERRATA_CPU4 },
+         { STRING_COMMA_LEN ("cpu8"), SILICON_ERRATA_CPU8 },
+         { STRING_COMMA_LEN ("cpu11"), SILICON_ERRATA_CPU11 },
+         { STRING_COMMA_LEN ("cpu12"), SILICON_ERRATA_CPU12 },
+         { STRING_COMMA_LEN ("cpu13"), SILICON_ERRATA_CPU13 },
+         { STRING_COMMA_LEN ("cpu19"), SILICON_ERRATA_CPU19 },
+         { STRING_COMMA_LEN ("cpu42"), SILICON_ERRATA_CPU42 },
+         { STRING_COMMA_LEN ("cpu42+"), SILICON_ERRATA_CPU42_PLUS },
+       };
+
+       do
+         {
+           for (i = ARRAY_SIZE (erratas); i--;)
+             if (strncasecmp (arg, erratas[i].name, erratas[i].length) == 0)
+               {
+                 if (c == OPTION_SILICON_ERRATA)
+                   silicon_errata_fix |= erratas[i].bitfield;
+                 else
+                   silicon_errata_warn |= erratas[i].bitfield;
+                 arg += erratas[i].length;
+                 break;
+               }
+           if (i < 0)
+             {
+               as_warn (_("Unrecognised CPU errata name starting here: %s"), arg);
+               break;
+             }
+           if (*arg == 0)
+             break;
+           if (*arg != ',')
+             as_warn (_("Expecting comma after CPU errata name, not: %s"), arg);
+           else
+             arg ++;
+         }
+       while (*arg != 0);
+      }
+      return 1;
+
     case OPTION_MMCU:
       if (arg == NULL)
        as_fatal (_("MCU option requires a name\n"));
@@ -1487,6 +1552,8 @@ const char *md_shortopts = "mm:,mP,mQ,ml,mN,mn,my,mY";
 
 struct option md_longopts[] =
 {
+  {"msilicon-errata", required_argument, NULL, OPTION_SILICON_ERRATA},
+  {"msilicon-errata-warn", required_argument, NULL, OPTION_SILICON_ERRATA_WARN},
   {"mmcu", required_argument, NULL, OPTION_MMCU},
   {"mcpu", required_argument, NULL, OPTION_MCPU},
   {"mP", no_argument, NULL, OPTION_POLYMORPHS},
@@ -1509,6 +1576,10 @@ md_show_usage (FILE * stream)
           _("MSP430 options:\n"
             "  -mmcu=<msp430-name>     - select microcontroller type\n"
              "  -mcpu={430|430x|430xv2} - select microcontroller architecture\n"));
+  fprintf (stream,
+          _("  -msilicon-errata=<name>[,<name>...] - enable fixups for silicon errata\n"
+            "  -msilicon-errata-warn=<name>[,<name>...] - warn when a fixup might be needed\n"
+            "   supported errata names: cpu4, cpu8, cpu11, cpu12, cpu13, cpu19, cpu42, cpu42+\n"));
   fprintf (stream,
           _("  -mQ - enable relaxation at assembly time. DANGEROUS!\n"
             "  -mP - enable polymorph instructions\n"));
@@ -1746,14 +1817,14 @@ msp430_srcoperand (struct msp430_operand_s * op,
            }
          else if (x == 4)
            {
-#ifdef PUSH_1X_WORKAROUND
-             if (bin == 0x1200)
+             if (bin == 0x1200 && ! target_is_430x ())
                {
-                 /* Remove warning as confusing.
-                    as_warn (_("Hardware push bug workaround")); */
+                 /* CPU4: The shorter form of PUSH #4 is not supported on MSP430.  */
+                 if (silicon_errata_warn & SILICON_ERRATA_CPU4)
+                   as_warn (_("cpu4: not converting PUSH #4 to shorter form"));
+                 /* No need to check silicon_errata_fixes - this fix is always implemented.  */
                }
              else
-#endif
                {
                  op->reg = 2;
                  op->am = 2;
@@ -1763,14 +1834,13 @@ msp430_srcoperand (struct msp430_operand_s * op,
            }
          else if (x == 8)
            {
-#ifdef PUSH_1X_WORKAROUND
-             if (bin == 0x1200)
+             if (bin == 0x1200 && ! target_is_430x ())
                {
-                 /* Remove warning as confusing.
-                    as_warn (_("Hardware push bug workaround")); */
+                 /* CPU4: The shorter form of PUSH #8 is not supported on MSP430.  */
+                 if (silicon_errata_warn & SILICON_ERRATA_CPU4)
+                   as_warn (_("cpu4: not converting PUSH #8 to shorter form"));
                }
              else
-#endif
                {
                  op->reg = 2;
                  op->am = 3;
@@ -2003,6 +2073,14 @@ msp430_srcoperand (struct msp430_operand_s * op,
              op->ol = 0;
              return 0;
            }
+
+         if (op->reg == 1 && (x & 1))
+           {
+             if (silicon_errata_fix & SILICON_ERRATA_CPU8)
+               as_bad (_("CPU8: Stack pointer accessed with an odd offset"));
+             else if (silicon_errata_warn & SILICON_ERRATA_CPU8)
+               as_warn (_("CPU8: Stack pointer accessed with an odd offset"));
+           }
        }
       else if (op->exp.X_op == O_symbol)
        ;
@@ -2353,7 +2431,11 @@ try_encode_mova (bfd_boolean imm_op,
   return 0;
 }
 
-static bfd_boolean check_for_nop = FALSE;
+#define NOP_CHECK_INTERRUPT  (1 << 0)
+#define NOP_CHECK_CPU12      (1 << 1)
+#define NOP_CHECK_CPU19      (1 << 2)
+
+static signed int check_for_nop = 0;
 
 #define is_opcode(NAME) (strcmp (opcode->name, NAME) == 0)
 
@@ -2380,7 +2462,6 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
   const char * error_message;
   static signed int repeat_count = 0;
   bfd_boolean fix_emitted;
-  bfd_boolean nop_check_needed = FALSE;
 
   /* Opcode is the one from opcodes table
      line contains something like
@@ -2513,20 +2594,20 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
       repeat_count = 0;
     }
 
-  if (check_for_nop && is_opcode ("nop"))
-    check_for_nop = FALSE;
-
-  switch (fmt)
+  if (check_for_nop)
     {
-    case 0:                    /* Emulated.  */
-      switch (opcode->insn_opnumb)
+      if (! is_opcode ("nop"))
        {
-       case 0:
-         if (is_opcode ("eint") || is_opcode ("dint"))
+         bfd_boolean doit = FALSE;
+
+         do
            {
-             if (check_for_nop)
+             switch (check_for_nop & - check_for_nop)
                {
-                 if (warn_interrupt_nops)
+               case NOP_CHECK_INTERRUPT:
+                 if (warn_interrupt_nops
+                     || silicon_errata_warn & SILICON_ERRATA_CPU42
+                     || silicon_errata_warn & SILICON_ERRATA_CPU42_PLUS)
                    {
                      if (gen_interrupt_nops)
                        as_warn (_("NOP inserted between two instructions that change interrupt state"));
@@ -2534,18 +2615,56 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                        as_warn (_("a NOP might be needed here because of successive changes in interrupt state"));
                    }
 
-                 if (gen_interrupt_nops)
-                   {
-                     /* Emit a NOP between interrupt enable/disable.
-                        See 1.3.4.1 of the MSP430x5xx User Guide.  */
-                     insn_length += 2;
-                     frag = frag_more (2);
-                     bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
-                   }
-               }
+                 if (gen_interrupt_nops
+                     || silicon_errata_fix & SILICON_ERRATA_CPU42_PLUS)
+                   /* Emit a NOP between interrupt enable/disable.
+                      See 1.3.4.1 of the MSP430x5xx User Guide.  */
+                   doit = TRUE;
+                 break;
+
+               case NOP_CHECK_CPU12:
+                 if (silicon_errata_warn & SILICON_ERRATA_CPU12)
+                   as_warn (_("CPU12: CMP/BIT with PC destinstion ignores next instruction"));
+
+                 if (silicon_errata_fix & SILICON_ERRATA_CPU12)
+                   doit = TRUE;
+                 break;
+
+               case NOP_CHECK_CPU19:
+                 if (silicon_errata_warn & SILICON_ERRATA_CPU19)
+                   as_warn (_("CPU19: Instruction setting CPUOFF must be followed by a NOP"));
 
-             nop_check_needed = TRUE;
+                 if (silicon_errata_fix & SILICON_ERRATA_CPU19)
+                   doit = TRUE;
+                 break;
+                 
+               default:
+                 as_bad (_("internal error: unknown nop check state"));
+                 break;
+               }
+             check_for_nop &= ~ (check_for_nop & - check_for_nop);
+           }
+         while (check_for_nop);
+         
+         if (doit)
+           {
+             frag = frag_more (2);
+             bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
+             dwarf2_emit_insn (2);
            }
+       }
+
+      check_for_nop = 0;
+    }
+
+  switch (fmt)
+    {
+    case 0:                    /* Emulated.  */
+      switch (opcode->insn_opnumb)
+       {
+       case 0:
+         if (is_opcode ("eint") || is_opcode ("dint"))
+           check_for_nop |= NOP_CHECK_INTERRUPT;
 
          /* Set/clear bits instructions.  */
          if (extended_op)
@@ -2574,30 +2693,37 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
 
          bin |= (op1.reg | (op1.am << 7));
 
-         if (is_opcode ("clr") && bin == 0x4302 /* CLR R2*/)
+         /* If the PC is the destination...  */
+         if (op1.am == 0 && op1.reg == 0
+             /* ... and the opcode alters the SR.  */
+             && !(is_opcode ("bic") || is_opcode ("bis") || is_opcode ("mov")
+                  || is_opcode ("bicx") || is_opcode ("bisx") || is_opcode ("movx")))
            {
-             if (check_for_nop)
-               {
-                 if (warn_interrupt_nops)
-                   {
-                     if (gen_interrupt_nops)
-                       as_warn (_("NOP inserted between two instructions that change interrupt state"));
-                     else
-                       as_warn (_("a NOP might be needed here because of successive changes in interrupt state"));
-                   }
-
-                 if (gen_interrupt_nops)
-                   {
-                     /* Emit a NOP between interrupt enable/disable.
-                        See 1.3.4.1 of the MSP430x5xx User Guide.  */
-                     insn_length += 2;
-                     frag = frag_more (2);
-                     bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
-                   }
-               }
-
-             nop_check_needed = TRUE;
+             if (silicon_errata_fix & SILICON_ERRATA_CPU11)
+               as_bad (_("CPU11: PC is destinstion of SR altering instruction"));
+             else if (silicon_errata_warn & SILICON_ERRATA_CPU11)
+               as_warn (_("CPU11: PC is destinstion of SR altering instruction"));
            }
+         
+         /* If the status register is the destination...  */
+         if (op1.am == 0 && op1.reg == 2
+             /* ... and the opcode alters the SR.  */
+             && (is_opcode ("adc") || is_opcode ("dec") || is_opcode ("decd")
+                 || is_opcode ("inc") || is_opcode ("incd") || is_opcode ("inv")
+                 || is_opcode ("sbc") || is_opcode ("sxt")
+                 || is_opcode ("adcx") || is_opcode ("decx") || is_opcode ("decdx")
+                 || is_opcode ("incx") || is_opcode ("incdx") || is_opcode ("invx")
+                 || is_opcode ("sbcx")
+                 ))
+           {
+             if (silicon_errata_fix & SILICON_ERRATA_CPU13)
+               as_bad (_("CPU13: SR is destinstion of SR altering instruction"));
+             else if (silicon_errata_warn & SILICON_ERRATA_CPU13)
+               as_warn (_("CPU13: SR is destinstion of SR altering instruction"));
+           }
+         
+         if (is_opcode ("clr") && bin == 0x4302 /* CLR R2*/)
+           check_for_nop |= NOP_CHECK_INTERRUPT;
 
          /* Compute the entire instruction length, in bytes.  */
          op_length = (extended_op ? 2 : 0) + 2 + (op1.ol * 2);
@@ -2691,6 +2817,19 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
              break;
            }
 
+         /* If the status register is the destination...  */
+         if (op1.am == 0 && op1.reg == 2
+             /* ... and the opcode alters the SR.  */
+             && (is_opcode ("rla") || is_opcode ("rlc")
+                 || is_opcode ("rlax") || is_opcode ("rlcx")
+                 ))
+           {
+             if (silicon_errata_fix & SILICON_ERRATA_CPU13)
+               as_bad (_("CPU13: SR is destinstion of SR altering instruction"));
+             else if (silicon_errata_warn & SILICON_ERRATA_CPU13)
+               as_warn (_("CPU13: SR is destinstion of SR altering instruction"));
+           }
+         
          if (extended_op)
            {
              if (!addr_op)
@@ -3297,33 +3436,56 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
 
       bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7));
 
+      /* If the PC is the destination...  */
+      if (op2.am == 0 && op2.reg == 0
+         /* ... and the opcode alters the SR.  */
+         && !(is_opcode ("bic") || is_opcode ("bis") || is_opcode ("mov")
+              || is_opcode ("bicx") || is_opcode ("bisx") || is_opcode ("movx")))
+       {
+         if (silicon_errata_fix & SILICON_ERRATA_CPU11)
+           as_bad (_("CPU11: PC is destinstion of SR altering instruction"));
+         else if (silicon_errata_warn & SILICON_ERRATA_CPU11)
+           as_warn (_("CPU11: PC is destinstion of SR altering instruction"));
+       }
+         
+      /* If the status register is the destination...  */
+      if (op2.am == 0 && op2.reg == 2
+         /* ... and the opcode alters the SR.  */
+         && (is_opcode ("add") || is_opcode ("addc") || is_opcode ("and")
+             || is_opcode ("dadd") || is_opcode ("sub") || is_opcode ("subc")
+             || is_opcode ("xor")
+             || is_opcode ("addx") || is_opcode ("addcx") || is_opcode ("andx")
+             || is_opcode ("daddx") || is_opcode ("subx") || is_opcode ("subcx")
+             || is_opcode ("xorx")
+             ))
+       {
+         if (silicon_errata_fix & SILICON_ERRATA_CPU13)
+           as_bad (_("CPU13: SR is destinstion of SR altering instruction"));
+         else if (silicon_errata_warn & SILICON_ERRATA_CPU13)
+           as_warn (_("CPU13: SR is destinstion of SR altering instruction"));
+       }
+         
       if (   (is_opcode ("bic") && bin == 0xc232)
          || (is_opcode ("bis") && bin == 0xd232)
          || (is_opcode ("mov") && op2.mode == OP_REG && op2.reg == 2))
        {
-         if (check_for_nop)
-           {
-             if (warn_interrupt_nops)
-               {
-                 if (gen_interrupt_nops)
-                   as_warn (_("NOP inserted between two instructions that change interrupt state"));
-                 else
-                   as_warn (_("a NOP might be needed here because of successive changes in interrupt state"));
-               }
-
-             if (gen_interrupt_nops)
-               {
-                 /* Emit a NOP between interrupt enable/disable.
-                    See 1.3.4.1 of the MSP430x5xx User Guide.  */
-                 insn_length += 2;
-                 frag = frag_more (2);
-                 bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
-               }
-           }
-
-         nop_check_needed = TRUE;
+         /* Avoid false checks when a constant value is being put into the SR.  */
+         if (op1.mode == OP_EXP
+             && op1.exp.X_op == O_constant
+             && (op1.exp.X_add_number & 0x8) != 0x8)
+           ;
+         else
+           check_for_nop |= NOP_CHECK_INTERRUPT;
        }
 
+      if (((is_opcode ("bis") && bin == 0xd032)
+          || (is_opcode ("mov") && bin == 0x4032)
+          || (is_opcode ("xor") && bin == 0xe032))
+         && op1.mode == OP_EXP
+         && op1.exp.X_op == O_constant
+         && (op1.exp.X_add_number & 0x10) == 0x10)
+       check_for_nop |= NOP_CHECK_CPU19;
+
       /* Compute the entire length of the instruction in bytes.  */
       op_length = (extended_op ? 2 : 0)        /* The extension word.  */
        + 2                     /* The opcode */
@@ -3433,6 +3595,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
        }
 
       dwarf2_emit_insn (insn_length);
+
+      /* If the PC is the destination...  */
+      if (op2.am == 0 && op2.reg == 0
+         /* ... but the opcode does not alter the destination.  */
+         && (is_opcode ("cmp") || is_opcode ("bit") || is_opcode ("cmpx")))
+       check_for_nop |= NOP_CHECK_CPU12;
       break;
 
     case 2:                    /* Single-operand mostly instr.  */
@@ -3464,6 +3632,17 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          break;
        }
 
+      /* If the status register is the destination...  */
+      if (op1.am == 0 && op1.reg == 2
+         /* ... and the opcode alters the SR.  */
+         && (is_opcode ("rra") || is_opcode ("rrc") || is_opcode ("sxt")))
+       {
+         if (silicon_errata_fix & SILICON_ERRATA_CPU13)
+           as_bad (_("CPU13: SR is destinstion of SR altering instruction"));
+         else if (silicon_errata_warn & SILICON_ERRATA_CPU13)
+           as_warn (_("CPU13: SR is destinstion of SR altering instruction"));
+       }
+         
       insn_length = (extended_op ? 2 : 0) + 2 + (op1.ol * 2);
       frag = frag_more (insn_length);
       where = frag - frag_now->fr_literal;
@@ -3726,7 +3905,6 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
     }
 
   input_line_pointer = line;
-  check_for_nop = nop_check_needed;
   return 0;
 }
 
@@ -4461,8 +4639,8 @@ msp430_fix_adjustable (struct fix *fixp ATTRIBUTE_UNUSED)
 void
 msp430_md_end (void)
 {
-  if (check_for_nop == TRUE && warn_interrupt_nops)
-    as_warn ("assembly finished with the last instruction changing interrupt state - a NOP might be needed");
+  if (check_for_nop)
+    as_warn ("assembly finished without a possibly needed NOP instruction");
 
   bfd_elf_add_proc_attr_int (stdoutput, OFBA_MSPABI_Tag_ISA,
                             target_is_430x () ? 2 : 1);
index 2a372dbecef97fd93147365a9a17e959a149dab5..5b72c769892fe7e63e2f210ad630f1b946655634 100644 (file)
@@ -36,6 +36,40 @@ also enables NOP generation unless the @option{-mN} is also specified.
 selects the cpu architecture.  If the architecture is 430Xv2 then this
 also enables NOP generation unless the @option{-mN} is also specified.
 
+@item -msilicon-errata=@var{name}[,@var{name}@dots{}]
+Implements a fixup for named silicon errata.  Multiple silicon errata
+can be specified by multiple uses of the @option{-msilicon-errata}
+option and/or by including the errata names, separated by commas, on
+an individual @option{-msilicon-errata} option.  Errata names
+currently recognised by the assembler are:
+
+@table @code
+@item cpu4
+@code{PUSH #4} and @option{PUSH #8} need longer encodings on the
+MSP430.  This option is enabled by default, and cannot be disabled.
+@item cpu8
+Do not set the @code{SP} to an odd value.
+@item cpu11
+Do not update the @code{SR} and the @code{PC} in the same instruction.
+@item cpu12
+Do not use the @code{PC} in a @code{CMP} or @code{BIT} instruction.
+@item cpu13
+Do not use an arithmetic instruction to modify the @code{SR}.
+@item cpu19
+Insert @code{NOP} after @code{CPUOFF}.
+@item cpu42
+Warn where a @code{NOP} ought to be present after enabling interrupts.
+@item cpu42+
+Add @code{NOP} after enabling interrupts.
+@end table
+
+@item -msilicon-errata-warn=@var{name}[,@var{name}@dots{}]
+Like the @option{-msilicon-errata} option except that instead of
+fixing the specified errata, a warning message is issued instead.
+This option can be used alongside @option{-msilicon-errata} to
+generate messages whenever a problem is fixed, or on its own in order
+to inspect code for potential problems.
+
 @item -mP
 enables polymorph instructions handler.
 
index 07ec4c8a2803d462345f80178f581d8675866ae3..89d282f9268e6457f4431523930dfb4c8c0fbd98 100644 (file)
@@ -1,3 +1,14 @@
+2015-10-22  Nick Clifton  <nickc@redhat.com>
+
+       * gas/msp430/errata_fixes.s: New test source file.
+       * gas/msp430/errata_fixes.d: New test control file.
+       * gas/msp430/errata_warns.s: New test source file.
+       * gas/msp430/errata_warns.d: New test control file.
+       * gas/msp430/errata_warns.l: New test message file.
+       * gas/msp430/msp430.exp: Run the new tests.
+       * gas/msp430/bad.l: Update expected warning messages
+       * gas/msp430/msp430.exp: Run the new tests.
+
 2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
 
        * gas/i386/i386.exp: Run x86-64-gotpcrel.
index 8de13389993d9450069204e6245e4e8adb948e87..6cc3e3a299d64d024e2f285b310d82377e03b385 100644 (file)
@@ -7,8 +7,9 @@
 [^:]*:11: Error: instruction bis.a does not exist
 [^:]*:19: Warning: a NOP might be needed here because of successive changes in interrupt state
 [^:]*:20: Warning: a NOP might be needed here because of successive changes in interrupt state
+[^:]*:23: Warning: a NOP might be needed here because of successive changes in interrupt state
 [^:]*:25: Warning: a NOP might be needed here because of successive changes in interrupt state
 [^:]*:26: Warning: a NOP might be needed here because of successive changes in interrupt state
 [^:]*:27: Warning: a NOP might be needed here because of successive changes in interrupt state
 [^:]*:28: Warning: a NOP might be needed here because of successive changes in interrupt state
-[^:]*: Warning: assembly finished with the last instruction changing interrupt state - a NOP might be needed
+[^:]*: Warning: assembly finished without a possibly needed NOP instruction
diff --git a/gas/testsuite/gas/msp430/errata_fixes.d b/gas/testsuite/gas/msp430/errata_fixes.d
new file mode 100644 (file)
index 0000000..c116405
--- /dev/null
@@ -0,0 +1,23 @@
+#name: Fixes for Silicon Errata
+#source: errata_fixes.s
+#as: -msilicon-errata=cpu4,cpu12,cpu19
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> 30 12 04 00[    ]+push  #4              ;
+0+0004 <[^>]*> 30 12 08 00[    ]+push  #8              ;
+0+0008 <[^>]*> 10 c3[  ]+bic   #1,     r0      ;r3 As==01$
+0+000a <[^>]*> 10 d3[  ]+bis   #1,     r0      ;r3 As==01$
+0+000c <[^>]*> 10 43[  ]+br    #1              ;r3 As==01$
+0+000e <[^>]*> 10 92 c8 00[    ]+cmp   &0x00c8,r0      ;0x00c8
+0+0012 <[^>]*> 03 43[  ]+nop                   
+0+0014 <[^>]*> 00 b1[  ]+bit   r1,     r0      ;
+0+0016 <[^>]*> 03 43[  ]+nop                   
+0+0018 <[^>]*> 32 d0 10 00[    ]+bis   #16,    r2      ;#0x0010
+0+001c <[^>]*> 03 43[  ]+nop                   
+0+001e <[^>]*> 32 40 10 00[    ]+mov   #16,    r2      ;#0x0010
+0+0022 <[^>]*> 03 43[  ]+nop                   
+0+0024 <[^>]*> 32 e0 10 00[    ]+xor   #16,    r2      ;#0x0010
+0+0028 <[^>]*> 03 43[  ]+nop                   
diff --git a/gas/testsuite/gas/msp430/errata_fixes.s b/gas/testsuite/gas/msp430/errata_fixes.s
new file mode 100644 (file)
index 0000000..dd6d14d
--- /dev/null
@@ -0,0 +1,24 @@
+       .text
+errata:
+       .cpu    msp430
+       # CPU4: PUSH #4/#8 has to be encoded using the long form
+       push    #4
+       push    #8
+
+       # CPU11: The SR flags can be left in a bogus state after writing to the PC
+       # Instructions that do not set the SR flags are unaffected.
+       bic      #1, pc
+       bis      #1, pc
+       mov      #1, pc
+       
+       #CPU12: A CMP or BIT instruction with the PC as the second operand may
+       # not execute the instruction after it - so a NOP must be inserted.
+       cmp      &200, PC
+       bit      r1, pc
+
+       #CPU19: Instructions that sets CPUOFF must be followed by a NOP
+       bis     #0x10, r2
+       mov     #0x10, r2
+       xor     #0x10, r2
+       nop
+       
\ No newline at end of file
diff --git a/gas/testsuite/gas/msp430/errata_warns.d b/gas/testsuite/gas/msp430/errata_warns.d
new file mode 100644 (file)
index 0000000..eef8c2e
--- /dev/null
@@ -0,0 +1,4 @@
+#name: Warning Messages for Silicon Errata
+#source: errata_warns.s
+#as: -msilicon-errata-warn=cpu4,cpu8,cpu11,cpu12,cpu13,cpu19
+#error-output: errata_warns.l
diff --git a/gas/testsuite/gas/msp430/errata_warns.l b/gas/testsuite/gas/msp430/errata_warns.l
new file mode 100644 (file)
index 0000000..52df6b9
--- /dev/null
@@ -0,0 +1,44 @@
+[^:]*: Assembler messages:
+[^:]*:5: Warning: cpu4: not converting PUSH #4 to shorter form
+[^:]*:6: Warning: cpu4: not converting PUSH #8 to shorter form
+[^:]*:11: Warning: CPU8: Stack pointer accessed with an odd offset
+[^:]*:12: Warning: CPU8: Stack pointer accessed with an odd offset
+[^:]*:13: Warning: CPU8: Stack pointer accessed with an odd offset
+[^:]*:14: Warning: CPU8: Stack pointer accessed with an odd offset
+[^:]*:15: Warning: CPU8: Stack pointer accessed with an odd offset
+[^:]*:18: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:19: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:20: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:21: Warning: CPU12: CMP/BIT with PC destinstion ignores next instruction
+[^:]*:21: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:22: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:23: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:24: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:25: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:26: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:30: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:31: Warning: CPU12: CMP/BIT with PC destinstion ignores next instruction
+[^:]*:31: Warning: CPU11: PC is destinstion of SR altering instruction
+[^:]*:34: Warning: CPU12: CMP/BIT with PC destinstion ignores next instruction
+[^:]*:34: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:35: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:36: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:37: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:38: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:39: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:40: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:41: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:42: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:43: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:44: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:45: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:46: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:47: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:48: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:49: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:50: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:51: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:52: Warning: CPU13: SR is destinstion of SR altering instruction
+[^:]*:56: Warning: CPU19: Instruction setting CPUOFF must be followed by a NOP
+[^:]*:57: Warning: CPU19: Instruction setting CPUOFF must be followed by a NOP
+[^:]*:57: Warning: CPU13: SR is destinstion of SR altering instruction
diff --git a/gas/testsuite/gas/msp430/errata_warns.s b/gas/testsuite/gas/msp430/errata_warns.s
new file mode 100644 (file)
index 0000000..c67d9c7
--- /dev/null
@@ -0,0 +1,59 @@
+       .text
+errata:
+       .cpu    msp430
+       # CPU4: PUSH #4/#8 has to be encoded using the long form
+       push    #4
+       push    #8
+
+       # CPU8: Do not use odd offsets with the stack pointer
+       .set fred,3
+       .set bert,1
+       mov.w   #4, 7(sp)
+       mov     3(r1), 5(r0)
+       mov.b   @r10+,fred-bert+1(sp)
+       add.w   #1,1(sp)
+       add.w   #7,-1(sp)
+
+       # CPU11: The SR flags can be left in a bogus state after writing to the PC
+       add.w    #3, pc
+       and      #1, pc
+       bit      #1, pc
+       dadd     #1, pc
+       inc      pc
+       incd     pc
+       sub      #1, pc
+       subc     #1, pc
+       xor      #1, pc
+
+       #CPU12: A CMP or BIT instruction with the PC as the second operand may
+       # not execute the instruction after it.
+       cmp      &200, PC
+       bit      r1, pc
+
+       #CPU13: Arithmetic operations with SR as the destination do not work.
+       add     #3, sr
+       adc     sr
+       addc    #3, sr
+       and     #3, sr
+       dadd    #3, sr
+       dec     sr
+       decd    sr
+       inc     sr
+       incd    sr
+       inv     sr
+       rla     sr
+       rlc     sr
+       rra     sr
+       rrc     sr
+       sbc     sr
+       sub     #3, sr
+       subc    #3, sr
+       sxt     sr
+       xor     #3, sr
+
+       #CPU19: Instructions that sets CPUOFF must be followed by a NOP
+       bis     #0x10, r2
+       mov     #0x10, r2
+       xor     #0x10, r2
+       nop
+       
\ No newline at end of file
index 78aa7641729028643a20f2473dac923a5d8ea94c..7742f554ed3e3f20f11dd928d88d774746829778 100644 (file)
@@ -22,4 +22,6 @@ if [expr [istarget "msp430-*-*"]]  then {
     run_dump_test "opcode"
     run_dump_test "msp430x"
     run_dump_test "bad"
+    run_dump_test "errata_warns"
+    run_dump_test "errata_fixes"
 }