Tighten the constraints for warning about NOPs for the MSP 430 ISA, so NOPs are only...
authorJozef Lawrynowicz <jozef.l@mittosystems.com>
Tue, 27 Nov 2018 12:25:09 +0000 (12:25 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 27 Nov 2018 12:25:09 +0000 (12:25 +0000)
* config/tc-msp430.c (is_dint): New.
(is_eint): New.
(gen_nop): New.
(warn_eint_nop): New.
(warn_unsure_interrupt): New.
(msp430_operands): Determine the effect MOV #N,SR insns have on
interrupt state.
Only emit NOP warnings for 430 ISA in certain situations.
(msp430_md_end): Only warn about an EINT at the end of the file
if NOP warnings are enabled.
* testsuite/gas/msp430/bad.l: Adjust expected output for new warnings.
* testsuite/gas/msp430/msp430.exp: Run new tests.
* testsuite/gas/msp430/nop-dint-430.d: New.
* testsuite/gas/msp430/nop-dint-430.l: New.
* testsuite/gas/msp430/nop-dint-430x-ignore.d: New.
* testsuite/gas/msp430/nop-dint-430x-silent.d: New.
* testsuite/gas/msp430/nop-dint-430x.d: New.
* testsuite/gas/msp430/nop-dint-430x.l: New.
* testsuite/gas/msp430/nop-dint.s: New.
* testsuite/gas/msp430/nop-eint-430.d: New.
* testsuite/gas/msp430/nop-eint-430.l: New.
* testsuite/gas/msp430/nop-eint-430x-ignore.d: New.
* testsuite/gas/msp430/nop-eint-430x-silent.d: New.
* testsuite/gas/msp430/nop-eint-430x.d: New.
* testsuite/gas/msp430/nop-eint-430x.l: New.
* testsuite/gas/msp430/nop-eint.s: New.
* testsuite/gas/msp430/nop-int-430.d: New.
* testsuite/gas/msp430/nop-int-430.l: New.
* testsuite/gas/msp430/nop-int-430x-silent.d: New.
* testsuite/gas/msp430/nop-int-430x.d: New.
* testsuite/gas/msp430/nop-int-430x.l: New.
* testsuite/gas/msp430/nop-int.s: New.

24 files changed:
gas/ChangeLog
gas/config/tc-msp430.c
gas/testsuite/gas/msp430/bad.l
gas/testsuite/gas/msp430/msp430.exp
gas/testsuite/gas/msp430/nop-dint-430.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-dint-430.l [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-dint-430x-ignore.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-dint-430x-silent.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-dint-430x.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-dint-430x.l [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-dint.s [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-eint-430.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-eint-430.l [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-eint-430x-ignore.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-eint-430x-silent.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-eint-430x.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-eint-430x.l [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-eint.s [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-int-430.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-int-430.l [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-int-430x-silent.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-int-430x.d [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-int-430x.l [new file with mode: 0644]
gas/testsuite/gas/msp430/nop-int.s [new file with mode: 0644]

index 4b02996..112b0f5 100644 (file)
@@ -1,3 +1,38 @@
+2018-11-27  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
+
+       * config/tc-msp430.c (is_dint): New.
+       (is_eint): New.
+       (gen_nop): New.
+       (warn_eint_nop): New.
+       (warn_unsure_interrupt): New.
+       (msp430_operands): Determine the effect MOV #N,SR insns have on
+       interrupt state.
+       Only emit NOP warnings for 430 ISA in certain situations.
+       (msp430_md_end): Only warn about an EINT at the end of the file
+       if NOP warnings are enabled.
+       * testsuite/gas/msp430/bad.l: Adjust expected output for new warnings.
+       * testsuite/gas/msp430/msp430.exp: Run new tests.
+       * testsuite/gas/msp430/nop-dint-430.d: New.
+       * testsuite/gas/msp430/nop-dint-430.l: New.
+       * testsuite/gas/msp430/nop-dint-430x-ignore.d: New.
+       * testsuite/gas/msp430/nop-dint-430x-silent.d: New.
+       * testsuite/gas/msp430/nop-dint-430x.d: New.
+       * testsuite/gas/msp430/nop-dint-430x.l: New.
+       * testsuite/gas/msp430/nop-dint.s: New.
+       * testsuite/gas/msp430/nop-eint-430.d: New.
+       * testsuite/gas/msp430/nop-eint-430.l: New.
+       * testsuite/gas/msp430/nop-eint-430x-ignore.d: New.
+       * testsuite/gas/msp430/nop-eint-430x-silent.d: New.
+       * testsuite/gas/msp430/nop-eint-430x.d: New.
+       * testsuite/gas/msp430/nop-eint-430x.l: New.
+       * testsuite/gas/msp430/nop-eint.s: New.
+       * testsuite/gas/msp430/nop-int-430.d: New.
+       * testsuite/gas/msp430/nop-int-430.l: New.
+       * testsuite/gas/msp430/nop-int-430x-silent.d: New.
+       * testsuite/gas/msp430/nop-int-430x.d: New.
+       * testsuite/gas/msp430/nop-int-430x.l: New.
+       * testsuite/gas/msp430/nop-int.s: New.
+
 2018-11-23  Andre Vieira  <andre.simoesdiasvieira@arm.com>
 
        * testsuite/gas/arm/bl-local-v4t.d: Remove
index bebae6e..d4b2407 100644 (file)
@@ -2495,6 +2495,79 @@ static signed int check_for_nop = 0;
 
 #define is_opcode(NAME) (strcmp (opcode->name, NAME) == 0)
 
+/* is_{e,d}int only check the explicit enabling/disabling of interrupts.
+   For MOV insns, more sophisticated processing is needed to determine if they
+   result in enabling/disabling interrupts.  */
+#define is_dint(OPCODE, BIN) ((strcmp (OPCODE, "dint") == 0) \
+                                  || ((strcmp (OPCODE, "bic") == 0) \
+                                      && BIN == 0xc232) \
+                                  || ((strcmp (OPCODE, "clr") == 0) \
+                                      && BIN == 0x4302))
+
+#define is_eint(OPCODE, BIN) ((strcmp (OPCODE, "eint") == 0) \
+                                  || ((strcmp (OPCODE, "bis") == 0) \
+                                      && BIN == 0xd232))
+
+const char * const INSERT_NOP_BEFORE_EINT = "NOP inserted here, before an interrupt enable instruction";
+const char * const INSERT_NOP_AFTER_DINT = "NOP inserted here, after an interrupt disable instruction";
+const char * const INSERT_NOP_AFTER_EINT = "NOP inserted here, after an interrupt enable instruction";
+const char * const INSERT_NOP_BEFORE_UNKNOWN = "NOP inserted here, before this interrupt state change";
+const char * const INSERT_NOP_AFTER_UNKNOWN ="NOP inserted here, after the instruction that changed interrupt state";
+const char * const INSERT_NOP_AT_EOF = "NOP inserted after the interrupt state change at the end of the file";
+
+const char * const WARN_NOP_BEFORE_EINT = "a NOP might be needed here, before an interrupt enable instruction";
+const char * const WARN_NOP_AFTER_DINT = "a NOP might be needed here, after an interrupt disable instruction";
+const char * const WARN_NOP_AFTER_EINT = "a NOP might be needed here, after an interrupt enable instruction";
+const char * const WARN_NOP_BEFORE_UNKNOWN = "a NOP might be needed here, before this interrupt state change";
+const char * const WARN_NOP_AFTER_UNKNOWN = "a NOP might also be needed here, after the instruction that changed interrupt state";
+const char * const WARN_NOP_AT_EOF = "a NOP might be needed after the interrupt state change at the end of the file";
+
+static void
+gen_nop (void)
+{
+  char *frag;
+  frag = frag_more (2);
+  bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
+  dwarf2_emit_insn (2);
+}
+
+/* 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.  */
+      || prev_insn_is_dint
+      /* 430 ISA does not require a NOP before EINT.  */
+      || (! target_is_430x ()))
+    return;
+  if (gen_interrupt_nops)
+    {
+      gen_nop ();
+      if (warn_interrupt_nops)
+       as_warn (_(INSERT_NOP_BEFORE_EINT));
+    }
+  else if (warn_interrupt_nops)
+    as_warn (_(WARN_NOP_BEFORE_EINT));
+}
+
+/* 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)
+{
+  /* Since this could enable or disable interrupts, need to add/warn about
+     adding a NOP before and after this insn.  */
+  if (gen_interrupt_nops)
+    {
+      gen_nop ();
+      if (warn_interrupt_nops)
+       as_warn (_(INSERT_NOP_BEFORE_UNKNOWN));
+    }
+  else if (warn_interrupt_nops)
+    as_warn (_(WARN_NOP_BEFORE_UNKNOWN));
+}
+
 /* Parse instruction operands.
    Return binary opcode.  */
 
@@ -2519,6 +2592,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
   const char * error_message;
   static signed int repeat_count = 0;
   static bfd_boolean prev_insn_is_nop = FALSE;
+  static bfd_boolean prev_insn_is_dint = FALSE;
+  static bfd_boolean prev_insn_is_eint = FALSE;
+  /* We might decide before the end of the function that the current insn is
+     equivalent to DINT/EINT.  */
+  bfd_boolean this_insn_is_dint = FALSE;
+  bfd_boolean this_insn_is_eint = FALSE;
   bfd_boolean fix_emitted;
 
   /* Opcode is the one from opcodes table
@@ -2654,29 +2733,69 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
       repeat_count = 0;
     }
 
+  /* The previous instruction set this flag if it wants to check if this insn
+     is a NOP.  */
   if (check_for_nop)
     {
       if (! is_opcode ("nop"))
        {
-         bfd_boolean doit = FALSE;
-
          do
            {
              switch (check_for_nop & - check_for_nop)
                {
                case NOP_CHECK_INTERRUPT:
-                 if (warn_interrupt_nops)
+                 /* NOP_CHECK_INTERRUPT rules:
+                    1.  430 and 430x ISA require a NOP after DINT.
+                    2.  Only the 430x ISA requires NOP before EINT (this has
+                       been dealt with in the previous call to this function).
+                    3.  Only the 430x ISA requires NOP after every EINT.
+                       CPU42 errata.  */
+                 if (gen_interrupt_nops || warn_interrupt_nops)
                    {
-                     if (gen_interrupt_nops)
-                       as_warn (_("NOP inserted between two instructions that change interrupt state"));
+                     if (prev_insn_is_dint)
+                       {
+                         if (gen_interrupt_nops)
+                           {
+                             gen_nop ();
+                             if (warn_interrupt_nops)
+                               as_warn (_(INSERT_NOP_AFTER_DINT));
+                           }
+                         else
+                           as_warn (_(WARN_NOP_AFTER_DINT));
+                       }
+                     else if (prev_insn_is_eint)
+                       {
+                         if (gen_interrupt_nops)
+                           {
+                             gen_nop ();
+                             if (warn_interrupt_nops)
+                               as_warn (_(INSERT_NOP_AFTER_EINT));
+                           }
+                         else
+                           as_warn (_(WARN_NOP_AFTER_EINT));
+                       }
+                     /* If we get here it's because the last instruction was
+                        determined to either disable or enable interrupts, but
+                        we're not sure which.
+                        We have no information yet about what effect the
+                        current instruction has on interrupts, that has to be
+                        sorted out later.
+                        The last insn may have required a NOP after it, so we
+                        deal with that now.  */
                      else
-                       as_warn (_("a NOP might be needed here because of successive changes in interrupt state"));
+                       {
+                         if (gen_interrupt_nops)
+                           {
+                             gen_nop ();
+                             if (warn_interrupt_nops)
+                               as_warn (_(INSERT_NOP_AFTER_UNKNOWN));
+                           }
+                         else
+                           /* warn_unsure_interrupt was called on the previous
+                              insn.  */
+                           as_warn (_(WARN_NOP_AFTER_UNKNOWN));
+                       }
                    }
-
-                 if (gen_interrupt_nops)
-                   /* Emit a NOP between interrupt enable/disable.
-                      See 1.3.4.1 of the MSP430x5xx User Guide.  */
-                   doit = TRUE;
                  break;
 
                case NOP_CHECK_CPU12:
@@ -2684,7 +2803,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                    as_warn (_("CPU12: CMP/BIT with PC destination ignores next instruction"));
 
                  if (silicon_errata_fix & SILICON_ERRATA_CPU12)
-                   doit = TRUE;
+                   gen_nop ();
                  break;
 
                case NOP_CHECK_CPU19:
@@ -2692,7 +2811,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                    as_warn (_("CPU19: Instruction setting CPUOFF must be followed by a NOP"));
 
                  if (silicon_errata_fix & SILICON_ERRATA_CPU19)
-                   doit = TRUE;
+                   gen_nop ();
                  break;
                  
                default:
@@ -2702,15 +2821,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
              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;
     }
 
@@ -2721,24 +2832,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
        {
        case 0:
          if (is_opcode ("eint"))
-           {
-             if (! prev_insn_is_nop)
-               {
-                 if (gen_interrupt_nops)
-                   {
-                     frag = frag_more (2);
-                     bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag);
-                     dwarf2_emit_insn (2);
-
-                     if (warn_interrupt_nops)
-                       as_warn (_("inserting a NOP before EINT"));
-                   }
-                 else if (warn_interrupt_nops)
-                   as_warn (_("a NOP might be needed before the EINT"));
-               }
-           }
-         else if (is_opcode ("dint"))
-           check_for_nop |= NOP_CHECK_INTERRUPT;
+           warn_eint_nop (prev_insn_is_nop, prev_insn_is_dint);
 
          /* Set/clear bits instructions.  */
          if (extended_op)
@@ -2796,9 +2890,6 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
                as_warn (_("CPU13: SR is destination 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);
          insn_length += op_length;
@@ -2896,6 +2987,8 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
              /* ... and the opcode alters the SR.  */
              && (is_opcode ("rla") || is_opcode ("rlc")
                  || is_opcode ("rlax") || is_opcode ("rlcx")
+                 || is_opcode ("sxt") || is_opcode ("sxtx")
+                 || is_opcode ("swpb")
                  ))
            {
              if (silicon_errata_fix & SILICON_ERRATA_CPU13)
@@ -3447,6 +3540,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
        }
       break;
 
+      /* FIXME: Emit warning when dest reg SR(R2) is addressed with .B or .A.
+        From f5 ref man 6.3.3:
+          The 16-bit Status Register (SR, also called R2), used as a source or
+          destination register, can only be used in register mode addressed
+          with word instructions.  */
+
     case 1:                    /* Format 1, double operand.  */
       line = extract_operand (line, l1, sizeof (l1));
       line = extract_operand (line, l2, sizeof (l2));
@@ -3501,20 +3600,9 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          else if (silicon_errata_warn & SILICON_ERRATA_CPU13)
            as_warn (_("CPU13: SR is destination 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))
-       {
-         /* 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;
-       }
 
+      /* Chain these checks for SR manipulations so we can warn if they are not
+        caught.  */
       if (((is_opcode ("bis") && bin == 0xd032)
           || (is_opcode ("mov") && bin == 0x4032)
           || (is_opcode ("xor") && bin == 0xe032))
@@ -3522,6 +3610,60 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
          && op1.exp.X_op == O_constant
          && (op1.exp.X_add_number & 0x10) == 0x10)
        check_for_nop |= NOP_CHECK_CPU19;
+      else if ((is_opcode ("mov") && op2.mode == OP_REG && op2.reg == 2))
+       {
+         /* Any MOV with the SR as the destination either enables or disables
+            interrupts.  */
+         if (op1.mode == OP_EXP
+             && op1.exp.X_op == O_constant)
+           {
+             if ((op1.exp.X_add_number & 0x8) == 0x8)
+               {
+                 /* The GIE bit is being set.  */
+                 warn_eint_nop (prev_insn_is_nop, prev_insn_is_dint);
+                 this_insn_is_eint = TRUE;
+               }
+             else
+               /* The GIE bit is being cleared.  */
+               this_insn_is_dint = TRUE;
+           }
+         /* If an immediate value which is covered by the constant generator
+            is the src, then op1 will have been changed to either R2 or R3 by
+            this point.
+            The only constants covered by CG1 and CG2, which have bit 3 set
+            and therefore would enable interrupts when writing to the SR, are
+            R2 with addresing mode 0b11 and R3 with 0b11.
+            The addressing mode is in bits 5:4 of the binary opcode.  */
+         else if (op1.mode == OP_REG
+                  && (op1.reg == 2 || op1.reg == 3)
+                  && (bin & 0x30) == 0x30)
+           {
+             warn_eint_nop (prev_insn_is_nop, prev_insn_is_dint);
+             this_insn_is_eint = TRUE;
+           }
+         /* Any other use of the constant generator with destination R2, will
+            disable interrupts.  */
+         else if (op1.mode == OP_REG
+                  && (op1.reg == 2 || op1.reg == 3))
+           this_insn_is_dint = TRUE;
+         else
+           {
+             /* 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 ();
+             check_for_nop |= NOP_CHECK_INTERRUPT;
+           }
+       }
+      else if (is_eint (opcode->name, bin))
+       warn_eint_nop (prev_insn_is_nop, prev_insn_is_dint);
+      else if ((bin & 0x32) == 0x32)
+       {
+         /* Double-operand insn with the As==0b11 and Rdst==0x2 will result in
+          * an interrupt state change if a write happens.  */
+         /* FIXME: How strict to be here? */
+         ;
+       }
 
       /* Compute the entire length of the instruction in bytes.  */
       op_length = (extended_op ? 2 : 0)        /* The extension word.  */
@@ -3959,11 +4101,34 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
       as_bad (_("Illegal instruction or not implemented opcode."));
     }
 
-  if (is_opcode ("nop"))
-    prev_insn_is_nop = TRUE;
-  else
-    prev_insn_is_nop = FALSE;
-           
+    if (is_opcode ("nop"))
+      {
+       prev_insn_is_nop = TRUE;
+       prev_insn_is_dint = FALSE;
+       prev_insn_is_eint = FALSE;
+      }
+    else if (this_insn_is_dint || is_dint (opcode->name, bin))
+      {
+       prev_insn_is_dint = TRUE;
+       prev_insn_is_eint = FALSE;
+       prev_insn_is_nop = FALSE;
+       check_for_nop |= NOP_CHECK_INTERRUPT;
+      }
+    /* NOP is not needed after EINT for 430 ISA.  */
+    else if (target_is_430x () && (this_insn_is_eint || is_eint (opcode->name, bin)))
+      {
+       prev_insn_is_eint = TRUE;
+       prev_insn_is_nop = FALSE;
+       prev_insn_is_dint = FALSE;
+       check_for_nop |= NOP_CHECK_INTERRUPT;
+      }
+    else
+      {
+       prev_insn_is_nop = FALSE;
+       prev_insn_is_dint = FALSE;
+       prev_insn_is_eint = FALSE;
+      }
+
   input_line_pointer = line;
   return 0;
 }
@@ -4699,7 +4864,16 @@ void
 msp430_md_end (void)
 {
   if (check_for_nop)
-    as_warn ("assembly finished without a possibly needed NOP instruction");
+    {
+      if (gen_interrupt_nops)
+       {
+         gen_nop ();
+         if (warn_interrupt_nops)
+           as_warn (INSERT_NOP_AT_EOF);
+       }
+      else if (warn_interrupt_nops)
+       as_warn (_(WARN_NOP_AT_EOF));
+    }
 
   bfd_elf_add_proc_attr_int (stdoutput, OFBA_MSPABI_Tag_ISA,
                             target_is_430x () ? 2 : 1);
index f466513..7b68583 100644 (file)
@@ -4,14 +4,15 @@
 [^:]*:8: Error: junk found after instruction: mov.cd r1,r2
 [^:]*:9: Error: junk found after instruction: mov.cd r1,r2
 [^:]*:10: Warning: no size modifier after period, .w assumed
+[^:]*:10: Warning: a NOP might be needed here, before this interrupt state change
 [^:]*:11: Error: instruction bis.a does not exist
-[^:]*:16: Warning: a NOP might be needed here because of successive changes in interrupt state
-[^:]*:16: Warning: a NOP might be needed before the EINT
-[^:]*:25: Warning: a NOP might be needed here because of successive changes in interrupt state
-[^:]*:25: Warning: a NOP might be needed before the EINT
-[^:]*:29: Warning: a NOP might be needed here because of successive changes in interrupt state
-[^:]*:31: Warning: a NOP might be needed here because of successive changes in interrupt state
-[^:]*:32: Warning: a NOP might be needed here because of successive changes in interrupt state
-[^:]*:33: Warning: a NOP might be needed here because of successive changes in interrupt state
-[^:]*:34: Warning: a NOP might be needed here because of successive changes in interrupt state
-[^:]*: Warning: assembly finished without a possibly needed NOP instruction
+[^:]*:16: Warning: a NOP might also be needed here, after the instruction that changed interrupt state
+[^:]*:16: Warning: a NOP might be needed here, before an interrupt enable instruction
+[^:]*:25: Warning: a NOP might be needed here, after an interrupt disable instruction
+[^:]*:26: Warning: a NOP might be needed here, after an interrupt enable instruction
+[^:]*:29: Warning: a NOP might be needed here, after an interrupt disable instruction
+[^:]*:31: Warning: a NOP might be needed here, after an interrupt disable instruction
+[^:]*:32: Warning: a NOP might be needed here, after an interrupt disable instruction
+[^:]*:33: Warning: a NOP might be needed here, after an interrupt disable instruction
+[^:]*:34: Warning: a NOP might be needed here, after an interrupt enable instruction
+[^:]*: Warning: a NOP might be needed after the interrupt state change at the end of the file
index 5e77b9b..1bc45be 100644 (file)
@@ -27,4 +27,15 @@ if [expr [istarget "msp430-*-*"]]  then {
     run_dump_test "high-data-bss-sym" { { as "-mdata-region=upper" } }
     run_dump_test "high-data-bss-sym" { { as "-mdata-region=either" } }
     run_dump_test "pr22133"
+    run_dump_test "nop-int-430"
+    run_dump_test "nop-int-430x"
+    run_dump_test "nop-int-430x-silent"
+    run_dump_test "nop-eint-430"
+    run_dump_test "nop-eint-430x"
+    run_dump_test "nop-eint-430x-silent"
+    run_dump_test "nop-eint-430x-ignore"
+    run_dump_test "nop-dint-430"
+    run_dump_test "nop-dint-430x"
+    run_dump_test "nop-dint-430x-silent"
+    run_dump_test "nop-dint-430x-ignore"
 }
diff --git a/gas/testsuite/gas/msp430/nop-dint-430.d b/gas/testsuite/gas/msp430/nop-dint-430.d
new file mode 100644 (file)
index 0000000..99eb00b
--- /dev/null
@@ -0,0 +1,32 @@
+#name: DINT NOP Insertions (MSP430 CPU)
+#source: nop-dint.s
+#as: -my -mn -mcpu=430
+#warning_output: nop-dint-430.l
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+Disassembly of section .text:
+0x0+000 32 c2[         ]+dint[         ]+
+0x0+002 03 43[         ]+nop[  ]+
+0x0+004 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+008 32 c2[         ]+dint[         ]+
+0x0+00a 03 43[         ]+nop[  ]+
+0x0+00c 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+010 32 c2[         ]+dint[         ]+
+0x0+012 03 43[         ]+nop[  ]+
+0x0+014 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+018 02 43[         ]+clr   r2              ;
+0x0+01a 03 43[         ]+nop[  ]+
+0x0+01c 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+020 32 40 07 00[   ]+mov   #7,     r2      ;
+0x0+024 03 43[         ]+nop[  ]+
+0x0+026 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+02a 32 40 07 f0[   ]+mov   #-4089, r2      ;#0xf007
+0x0+02e 03 43[         ]+nop[  ]+
+0x0+030 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+034 02 43[         ]+clr   r2              ;
+0x0+036 03 43[         ]+nop[  ]+
+0x0+038 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+03c 32 c2[         ]+dint[         ]+
+0x0+03e 03 43[         ]+nop[  ]+
diff --git a/gas/testsuite/gas/msp430/nop-dint-430.l b/gas/testsuite/gas/msp430/nop-dint-430.l
new file mode 100644 (file)
index 0000000..ab1adec
--- /dev/null
@@ -0,0 +1,9 @@
+[^:]*: Assembler messages:
+[^:]*:11: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:15: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:18: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:21: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:24: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:27: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:30: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*: Warning: NOP inserted after the interrupt state change at the end of the file
diff --git a/gas/testsuite/gas/msp430/nop-dint-430x-ignore.d b/gas/testsuite/gas/msp430/nop-dint-430x-ignore.d
new file mode 100644 (file)
index 0000000..e9265ae
--- /dev/null
@@ -0,0 +1,8 @@
+#name: Ignore DINT NOP Insertions (MSP430X CPU)
+#source: nop-dint.s
+#as: -mY -mcpu=430x
+#objdump: -d --prefix-addresses --show-raw-insn
+#failif
+#...
+0x0.*nop.*
+#...
diff --git a/gas/testsuite/gas/msp430/nop-dint-430x-silent.d b/gas/testsuite/gas/msp430/nop-dint-430x-silent.d
new file mode 100644 (file)
index 0000000..66c1052
--- /dev/null
@@ -0,0 +1,31 @@
+#name: Silent DINT NOP Insertions (MSP430X CPU)
+#source: nop-dint.s
+#as: -mY -mn -mcpu=430x
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+Disassembly of section .text:
+0x0+000 32 c2[         ]+dint[         ]+
+0x0+002 03 43[         ]+nop[  ]+
+0x0+004 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+008 32 c2[         ]+dint[         ]+
+0x0+00a 03 43[         ]+nop[  ]+
+0x0+00c 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+010 32 c2[         ]+dint[         ]+
+0x0+012 03 43[         ]+nop[  ]+
+0x0+014 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+018 02 43[         ]+clr   r2              ;
+0x0+01a 03 43[         ]+nop[  ]+
+0x0+01c 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+020 32 40 07 00[   ]+mov   #7,     r2      ;
+0x0+024 03 43[         ]+nop[  ]+
+0x0+026 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+02a 32 40 07 f0[   ]+mov   #-4089, r2      ;#0xf007
+0x0+02e 03 43[         ]+nop[  ]+
+0x0+030 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+034 02 43[         ]+clr   r2              ;
+0x0+036 03 43[         ]+nop[  ]+
+0x0+038 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+03c 32 c2[         ]+dint[         ]+
+0x0+03e 03 43[         ]+nop[  ]+
diff --git a/gas/testsuite/gas/msp430/nop-dint-430x.d b/gas/testsuite/gas/msp430/nop-dint-430x.d
new file mode 100644 (file)
index 0000000..ea74dfc
--- /dev/null
@@ -0,0 +1,32 @@
+#name: DINT NOP Insertions (MSP430X CPU)
+#source: nop-dint.s
+#as: -my -mn -mcpu=430x
+#warning_output: nop-dint-430.l
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+Disassembly of section .text:
+0x0+000 32 c2[         ]+dint[         ]+
+0x0+002 03 43[         ]+nop[  ]+
+0x0+004 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+008 32 c2[         ]+dint[         ]+
+0x0+00a 03 43[         ]+nop[  ]+
+0x0+00c 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+010 32 c2[         ]+dint[         ]+
+0x0+012 03 43[         ]+nop[  ]+
+0x0+014 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+018 02 43[         ]+clr   r2              ;
+0x0+01a 03 43[         ]+nop[  ]+
+0x0+01c 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+020 32 40 07 00[   ]+mov   #7,     r2      ;
+0x0+024 03 43[         ]+nop[  ]+
+0x0+026 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+02a 32 40 07 f0[   ]+mov   #-4089, r2      ;#0xf007
+0x0+02e 03 43[         ]+nop[  ]+
+0x0+030 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+034 02 43[         ]+clr   r2              ;
+0x0+036 03 43[         ]+nop[  ]+
+0x0+038 1a 42 00 00[   ]+mov   &0x0000,r10     ;0x0000
+0x0+03c 32 c2[         ]+dint[         ]+
+0x0+03e 03 43[         ]+nop[  ]+
diff --git a/gas/testsuite/gas/msp430/nop-dint-430x.l b/gas/testsuite/gas/msp430/nop-dint-430x.l
new file mode 100644 (file)
index 0000000..ab1adec
--- /dev/null
@@ -0,0 +1,9 @@
+[^:]*: Assembler messages:
+[^:]*:11: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:15: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:18: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:21: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:24: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:27: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:30: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*: Warning: NOP inserted after the interrupt state change at the end of the file
diff --git a/gas/testsuite/gas/msp430/nop-dint.s b/gas/testsuite/gas/msp430/nop-dint.s
new file mode 100644 (file)
index 0000000..3dc8019
--- /dev/null
@@ -0,0 +1,37 @@
+       .text
+
+;;; Test for NOP warnings when disabling interrupts, which are common to both
+;;; 430 and 430x ISA.
+;;; "MOV &FOO,r10" is used as an artbitrary statement which isn't a NOP, to
+;;; break up the instructions being tested.
+
+;;; Test NOP required after DINT
+       DINT
+
+       MOV &FOO,r10
+;;; Check aliases for which the GIE bit (bit 3) of the SR can be cleared
+;;; These should all cause warnings
+       BIC.W #8,R2
+       MOV &FOO,r10
+
+       BIC.W #8,SR
+       MOV &FOO,r10
+
+       MOV.W #0,R2
+       MOV &FOO,r10
+
+       MOV.W #7,R2
+       MOV &FOO,r10
+
+       MOV.W #0xf007,R2
+       MOV &FOO,r10
+
+       CLR R2
+       MOV &FOO,r10
+
+;;; The above hopefully covers the legitimate ways the SR might be cleared,
+;;; but there are other insns that can technically modify R2, but shouldn't be
+;;; used.
+
+;;; Test DINT at end of file
+       DINT
diff --git a/gas/testsuite/gas/msp430/nop-eint-430.d b/gas/testsuite/gas/msp430/nop-eint-430.d
new file mode 100644 (file)
index 0000000..37b2c6c
--- /dev/null
@@ -0,0 +1,31 @@
+#name: EINT NOP Insertions (MSP430 CPU)
+#source: nop-eint.s
+#as: -my -mn -mcpu=430
+#warning_output: nop-eint-430.l
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+
+Disassembly of section .text:
+0x0+0000 32 d2[        ]+eint[         ]+
+0x0+0002 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0006 32 d2[        ]+eint[         ]+
+0x0+0008 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+000c 32 d2[        ]+eint[         ]+
+0x0+000e 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0012 32 42[        ]+mov   #8,     r2      ;r2 As==11
+0x0+0014 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0018 32 40 0f 00[  ]+mov   #15,    r2      ;#0x000f
+0x0+001c 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0020 32 43[        ]+mov   #-1,    r2      ;r3 As==11
+0x0+0022 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0026 32 d2[        ]+eint[         ]+
+0x0+0028 32 c2[        ]+dint[         ]+
+0x0+002a 03 43[        ]+nop[  ]+
+0x0+002c 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0030 32 c2[        ]+dint[         ]+
+0x0+0032 03 43[        ]+nop[  ]+
+0x0+0034 32 d2[        ]+eint[         ]+
+0x0+0036 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+003a 32 d2[        ]+eint[         ]+
diff --git a/gas/testsuite/gas/msp430/nop-eint-430.l b/gas/testsuite/gas/msp430/nop-eint-430.l
new file mode 100644 (file)
index 0000000..a7bb342
--- /dev/null
@@ -0,0 +1,3 @@
+[^:]*: Assembler messages:
+[^:]*:36: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:39: Warning: NOP inserted here, after an interrupt disable instruction
diff --git a/gas/testsuite/gas/msp430/nop-eint-430x-ignore.d b/gas/testsuite/gas/msp430/nop-eint-430x-ignore.d
new file mode 100644 (file)
index 0000000..54066c0
--- /dev/null
@@ -0,0 +1,8 @@
+#name: Ignore EINT NOP Insertions (MSP430X CPU)
+#source: nop-eint.s
+#as: -mY -mcpu=430x
+#objdump: -d --prefix-addresses --show-raw-insn
+#failif
+#...
+0x0.*nop.*
+#...
diff --git a/gas/testsuite/gas/msp430/nop-eint-430x-silent.d b/gas/testsuite/gas/msp430/nop-eint-430x-silent.d
new file mode 100644 (file)
index 0000000..ee7b362
--- /dev/null
@@ -0,0 +1,47 @@
+#name: Silent EINT NOP Insertions (MSP430X CPU)
+#source: nop-eint.s
+#as: -mY -mn -mcpu=430x
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+
+Disassembly of section .text:
+0x0+0000 03 43[        ]+nop[  ]+
+0x0+0002 32 d2[        ]+eint[         ]+
+0x0+0004 03 43[        ]+nop[  ]+
+0x0+0006 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+000a 03 43[        ]+nop[  ]+
+0x0+000c 32 d2[        ]+eint[         ]+
+0x0+000e 03 43[        ]+nop[  ]+
+0x0+0010 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0014 03 43[        ]+nop[  ]+
+0x0+0016 32 d2[        ]+eint[         ]+
+0x0+0018 03 43[        ]+nop[  ]+
+0x0+001a 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+001e 03 43[        ]+nop[  ]+
+0x0+0020 32 42[        ]+mov   #8,     r2      ;r2 As==11
+0x0+0022 03 43[        ]+nop[  ]+
+0x0+0024 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0028 03 43[        ]+nop[  ]+
+0x0+002a 32 40 0f 00[  ]+mov   #15,    r2      ;#0x000f
+0x0+002e 03 43[        ]+nop[  ]+
+0x0+0030 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0034 03 43[        ]+nop[  ]+
+0x0+0036 32 43[        ]+mov   #-1,    r2      ;r3 As==11
+0x0+0038 03 43[        ]+nop[  ]+
+0x0+003a 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+003e 03 43[        ]+nop[  ]+
+0x0+0040 32 d2[        ]+eint[         ]+
+0x0+0042 03 43[        ]+nop[  ]+
+0x0+0044 32 c2[        ]+dint[         ]+
+0x0+0046 03 43[        ]+nop[  ]+
+0x0+0048 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+004c 32 c2[        ]+dint[         ]+
+0x0+004e 03 43[        ]+nop[  ]+
+0x0+0050 32 d2[        ]+eint[         ]+
+0x0+0052 03 43[        ]+nop[  ]+
+0x0+0054 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0058 03 43[        ]+nop[  ]+
+0x0+005a 32 d2[        ]+eint[         ]+
+0x0+005c 03 43[        ]+nop[  ]+
diff --git a/gas/testsuite/gas/msp430/nop-eint-430x.d b/gas/testsuite/gas/msp430/nop-eint-430x.d
new file mode 100644 (file)
index 0000000..a28459b
--- /dev/null
@@ -0,0 +1,48 @@
+#name: EINT NOP Insertions (MSP430X CPU)
+#source: nop-eint.s
+#as: -my -mn -mcpu=430x
+#warning_output: nop-eint-430x.l
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+
+Disassembly of section .text:
+0x0+0000 03 43[        ]+nop[  ]+
+0x0+0002 32 d2[        ]+eint[         ]+
+0x0+0004 03 43[        ]+nop[  ]+
+0x0+0006 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+000a 03 43[        ]+nop[  ]+
+0x0+000c 32 d2[        ]+eint[         ]+
+0x0+000e 03 43[        ]+nop[  ]+
+0x0+0010 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0014 03 43[        ]+nop[  ]+
+0x0+0016 32 d2[        ]+eint[         ]+
+0x0+0018 03 43[        ]+nop[  ]+
+0x0+001a 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+001e 03 43[        ]+nop[  ]+
+0x0+0020 32 42[        ]+mov   #8,     r2      ;r2 As==11
+0x0+0022 03 43[        ]+nop[  ]+
+0x0+0024 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0028 03 43[        ]+nop[  ]+
+0x0+002a 32 40 0f 00[  ]+mov   #15,    r2      ;#0x000f
+0x0+002e 03 43[        ]+nop[  ]+
+0x0+0030 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0034 03 43[        ]+nop[  ]+
+0x0+0036 32 43[        ]+mov   #-1,    r2      ;r3 As==11
+0x0+0038 03 43[        ]+nop[  ]+
+0x0+003a 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+003e 03 43[        ]+nop[  ]+
+0x0+0040 32 d2[        ]+eint[         ]+
+0x0+0042 03 43[        ]+nop[  ]+
+0x0+0044 32 c2[        ]+dint[         ]+
+0x0+0046 03 43[        ]+nop[  ]+
+0x0+0048 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+004c 32 c2[        ]+dint[         ]+
+0x0+004e 03 43[        ]+nop[  ]+
+0x0+0050 32 d2[        ]+eint[         ]+
+0x0+0052 03 43[        ]+nop[  ]+
+0x0+0054 1a 42 00 00[  ]+mov   &0x0000,r10     ;0x0000
+0x0+0058 03 43[        ]+nop[  ]+
+0x0+005a 32 d2[        ]+eint[         ]+
+0x0+005c 03 43[        ]+nop[  ]+
diff --git a/gas/testsuite/gas/msp430/nop-eint-430x.l b/gas/testsuite/gas/msp430/nop-eint-430x.l
new file mode 100644 (file)
index 0000000..0e97208
--- /dev/null
@@ -0,0 +1,20 @@
+[^:]*: Assembler messages:
+[^:]*:7: Warning: NOP inserted here, before an interrupt enable instruction
+[^:]*:9: Warning: NOP inserted here, after an interrupt enable instruction
+[^:]*:12: Warning: NOP inserted here, before an interrupt enable instruction
+[^:]*:13: Warning: NOP inserted here, after an interrupt enable instruction
+[^:]*:15: Warning: NOP inserted here, before an interrupt enable instruction
+[^:]*:16: Warning: NOP inserted here, after an interrupt enable instruction
+[^:]*:18: Warning: NOP inserted here, before an interrupt enable instruction
+[^:]*:19: Warning: NOP inserted here, after an interrupt enable instruction
+[^:]*:21: Warning: NOP inserted here, before an interrupt enable instruction
+[^:]*:22: Warning: NOP inserted here, after an interrupt enable instruction
+[^:]*:24: Warning: NOP inserted here, before an interrupt enable instruction
+[^:]*:25: Warning: NOP inserted here, after an interrupt enable instruction
+[^:]*:33: Warning: NOP inserted here, before an interrupt enable instruction
+[^:]*:34: Warning: NOP inserted here, after an interrupt enable instruction
+[^:]*:36: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:39: Warning: NOP inserted here, after an interrupt disable instruction
+[^:]*:41: Warning: NOP inserted here, after an interrupt enable instruction
+[^:]*:44: Warning: NOP inserted here, before an interrupt enable instruction
+[^:]*: Warning: NOP inserted after the interrupt state change at the end of the file
diff --git a/gas/testsuite/gas/msp430/nop-eint.s b/gas/testsuite/gas/msp430/nop-eint.s
new file mode 100644 (file)
index 0000000..07e3238
--- /dev/null
@@ -0,0 +1,44 @@
+       .text
+
+;;; Test for NOP warnings when enabling interrupts, which only applies to 430x
+;;; ISA.
+;;; "MOV &FOO,r10" is used as an artbitrary statement which isn't a NOP, to
+;;; break up the instructions being tested.
+  EINT
+
+  MOV &FOO,r10
+;;; Check aliases for which the GIE bit (bit 3) of the SR can be set
+;;; These should all cause warnings
+       BIS.W #8,R2
+       MOV &FOO,r10
+
+       BIS.W #8,SR
+       MOV &FOO,r10
+
+       MOV.W #8,R2
+       MOV &FOO,r10
+
+       MOV #0xf,R2
+       MOV &FOO,r10
+
+       MOV #0xffff,R2
+       MOV &FOO,r10
+
+;;; The above hopefully covers the legitimate ways the SR might be set
+;;; but there are other insns that can technically modify R2, but shouldn't be
+;;; used.
+
+;;; Verify EINT/DINT chained behaviour
+
+  EINT
+  DINT
+
+       MOV &FOO,r10
+
+  DINT
+  EINT
+
+       MOV &FOO,r10
+
+;;; Test EINT at end of file
+  EINT
diff --git a/gas/testsuite/gas/msp430/nop-int-430.d b/gas/testsuite/gas/msp430/nop-int-430.d
new file mode 100644 (file)
index 0000000..ae8ba53
--- /dev/null
@@ -0,0 +1,4 @@
+#name: Interrupt NOP Warnings (MSP430 CPU)
+#source: nop-int.s
+#as: -my -mcpu=430
+#warning_output: nop-int-430.l
diff --git a/gas/testsuite/gas/msp430/nop-int-430.l b/gas/testsuite/gas/msp430/nop-int-430.l
new file mode 100644 (file)
index 0000000..6c2a04d
--- /dev/null
@@ -0,0 +1,3 @@
+[^:]*: Assembler messages:
+[^:]*:60: Warning: a NOP might be needed here, after an interrupt disable instruction
+[^:]*:66: Warning: a NOP might be needed here, after an interrupt disable instruction
diff --git a/gas/testsuite/gas/msp430/nop-int-430x-silent.d b/gas/testsuite/gas/msp430/nop-int-430x-silent.d
new file mode 100644 (file)
index 0000000..5994b43
--- /dev/null
@@ -0,0 +1,5 @@
+#name: Silence Interrupt NOP Warnings (MSP430X CPU)
+#source: nop-int.s
+#as: -mY -mcpu=430x
+#objdump: -d --prefix-addresses --show-raw-insn
+#pass
diff --git a/gas/testsuite/gas/msp430/nop-int-430x.d b/gas/testsuite/gas/msp430/nop-int-430x.d
new file mode 100644 (file)
index 0000000..9e93ed3
--- /dev/null
@@ -0,0 +1,4 @@
+#name: Interrupt NOP Warnings (MSP430X CPU)
+#source: nop-int.s
+#as: -my -mcpu=430x
+#warning_output: nop-int-430x.l
diff --git a/gas/testsuite/gas/msp430/nop-int-430x.l b/gas/testsuite/gas/msp430/nop-int-430x.l
new file mode 100644 (file)
index 0000000..43f7ca2
--- /dev/null
@@ -0,0 +1,10 @@
+[^:]*: Assembler messages:
+[^:]*:13: Warning: a NOP might be needed here, before an interrupt enable instruction
+[^:]*:15: Warning: a NOP might be needed here, after an interrupt enable instruction
+[^:]*:17: Warning: a NOP might be needed here, before an interrupt enable instruction
+[^:]*:19: Warning: a NOP might be needed here, after an interrupt enable instruction
+[^:]*:41: Warning: a NOP might be needed here, after an interrupt enable instruction
+[^:]*:48: Warning: a NOP might be needed here, after an interrupt enable instruction
+[^:]*:60: Warning: a NOP might be needed here, after an interrupt disable instruction
+[^:]*:66: Warning: a NOP might be needed here, after an interrupt disable instruction
+[^:]*: Warning: a NOP might be needed after the interrupt state change at the end of the file
diff --git a/gas/testsuite/gas/msp430/nop-int.s b/gas/testsuite/gas/msp430/nop-int.s
new file mode 100644 (file)
index 0000000..efc8828
--- /dev/null
@@ -0,0 +1,74 @@
+  .text
+
+;;; Test some common instruction patterns for disabling/enabling interrupts.
+;;; "MOV &FOO,r10" is used as an artbitrary statement which isn't a NOP, to
+;;; break up the instructions being tested.
+
+fn1:
+;;; 1: Test EINT
+;; 430 ISA: NOP *not* required before *or* after EINT
+;; 430x ISA: NOP *is* required before *and* after EINT
+  MOV &FOO,r10
+
+  EINT
+
+  MOV &FOO,r10
+
+  BIS.W #8,SR          ; Alias for EINT
+
+  MOV &FOO,r10
+;;; 2: Test DINT
+;; 430 ISA: NOP *is* required after DINT
+;; 430x ISA: NOP *is* required after DINT
+  MOV &FOO,r10
+
+  DINT
+  NOP
+
+  MOV &FOO,r10
+
+  BIC.W #8,SR          ; Alias for DINT
+  NOP
+
+  MOV &FOO,r10
+;;; 3: Test EINT immediately before DINT
+;; 430 ISA: NOP *not* required.
+;; 430x ISA: NOP *is* required between EINT and DINT
+  MOV &FOO,r10
+
+  NOP
+  EINT
+  DINT
+  NOP
+
+  MOV &FOO,r10
+
+  NOP
+  BIS.W #8,SR          ; Alias for EINT
+  BIC.W #8,SR          ; Alias for DINT
+  NOP
+
+  MOV &FOO,r10
+;;; 4: Test DINT immediately before EINT
+;; 430 ISA: NOP *is* required after DINT.
+;; 430x ISA: NOP *is* required after DINT and before EINT. Ensure only one
+;; warning is emitted.
+  MOV &FOO,r10
+
+  NOP
+  DINT
+  EINT
+  NOP
+
+  MOV &FOO,r10
+
+  BIC.W #8,SR          ; Alias for DINT
+  BIS.W #8,SR          ; Alias for EINT
+  NOP
+
+  MOV &FOO,r10
+
+;;; 5: Test EINT last insn in file
+
+  NOP
+  EINT