This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Tighten the constraints for warning about NOPs for the MSP 430 ISA, so NOPs are only inserted/warned


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=35ba4bc019ba75eca36363164eeaae3f011b32c9

commit 35ba4bc019ba75eca36363164eeaae3f011b32c9
Author: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date:   Tue Nov 27 12:25:09 2018 +0000

    Tighten the constraints for warning about NOPs for the MSP 430 ISA, so NOPs are only inserted/warned about when needed.  Specifically: 430 and 430x ISA require a NOP after DINT.  Only the 430x ISA requires NOP before EINT.  Only the 430x ISA requires NOP after every EINT. CPU42 errata.
    
    	* 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.

Diff:
---
 gas/ChangeLog                                   |  35 +++
 gas/config/tc-msp430.c                          | 296 +++++++++++++++++++-----
 gas/testsuite/gas/msp430/bad.l                  |  21 +-
 gas/testsuite/gas/msp430/msp430.exp             |  11 +
 gas/testsuite/gas/msp430/nop-dint-430.d         |  32 +++
 gas/testsuite/gas/msp430/nop-dint-430.l         |   9 +
 gas/testsuite/gas/msp430/nop-dint-430x-ignore.d |   8 +
 gas/testsuite/gas/msp430/nop-dint-430x-silent.d |  31 +++
 gas/testsuite/gas/msp430/nop-dint-430x.d        |  32 +++
 gas/testsuite/gas/msp430/nop-dint-430x.l        |   9 +
 gas/testsuite/gas/msp430/nop-dint.s             |  37 +++
 gas/testsuite/gas/msp430/nop-eint-430.d         |  31 +++
 gas/testsuite/gas/msp430/nop-eint-430.l         |   3 +
 gas/testsuite/gas/msp430/nop-eint-430x-ignore.d |   8 +
 gas/testsuite/gas/msp430/nop-eint-430x-silent.d |  47 ++++
 gas/testsuite/gas/msp430/nop-eint-430x.d        |  48 ++++
 gas/testsuite/gas/msp430/nop-eint-430x.l        |  20 ++
 gas/testsuite/gas/msp430/nop-eint.s             |  44 ++++
 gas/testsuite/gas/msp430/nop-int-430.d          |   4 +
 gas/testsuite/gas/msp430/nop-int-430.l          |   3 +
 gas/testsuite/gas/msp430/nop-int-430x-silent.d  |   5 +
 gas/testsuite/gas/msp430/nop-int-430x.d         |   4 +
 gas/testsuite/gas/msp430/nop-int-430x.l         |  10 +
 gas/testsuite/gas/msp430/nop-int.s              |  74 ++++++
 24 files changed, 751 insertions(+), 71 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 4b02996..112b0f5 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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
diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c
index bebae6e..d4b2407 100644
--- a/gas/config/tc-msp430.c
+++ b/gas/config/tc-msp430.c
@@ -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);
diff --git a/gas/testsuite/gas/msp430/bad.l b/gas/testsuite/gas/msp430/bad.l
index f466513..7b68583 100644
--- a/gas/testsuite/gas/msp430/bad.l
+++ b/gas/testsuite/gas/msp430/bad.l
@@ -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
diff --git a/gas/testsuite/gas/msp430/msp430.exp b/gas/testsuite/gas/msp430/msp430.exp
index 5e77b9b..1bc45be 100644
--- a/gas/testsuite/gas/msp430/msp430.exp
+++ b/gas/testsuite/gas/msp430/msp430.exp
@@ -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
index 0000000..99eb00b
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-dint-430.d
@@ -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
index 0000000..ab1adec
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-dint-430.l
@@ -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
index 0000000..e9265ae
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-dint-430x-ignore.d
@@ -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
index 0000000..66c1052
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-dint-430x-silent.d
@@ -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
index 0000000..ea74dfc
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-dint-430x.d
@@ -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
index 0000000..ab1adec
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-dint-430x.l
@@ -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
index 0000000..3dc8019
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-dint.s
@@ -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
index 0000000..37b2c6c
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-eint-430.d
@@ -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
index 0000000..a7bb342
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-eint-430.l
@@ -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
index 0000000..54066c0
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-eint-430x-ignore.d
@@ -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
index 0000000..ee7b362
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-eint-430x-silent.d
@@ -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
index 0000000..a28459b
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-eint-430x.d
@@ -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
index 0000000..0e97208
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-eint-430x.l
@@ -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
index 0000000..07e3238
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-eint.s
@@ -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
index 0000000..ae8ba53
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-int-430.d
@@ -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
index 0000000..6c2a04d
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-int-430.l
@@ -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
index 0000000..5994b43
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-int-430x-silent.d
@@ -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
index 0000000..9e93ed3
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-int-430x.d
@@ -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
index 0000000..43f7ca2
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-int-430x.l
@@ -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
index 0000000..efc8828
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-int.s
@@ -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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]