[MSP430] Add options to toggle NOP warnings for possible interrupt state changes

Message ID 20190415151607.36eda867@jozef-kubuntu
State New
Headers show
Series
  • [MSP430] Add options to toggle NOP warnings for possible interrupt state changes
Related show

Commit Message

Jozef Lawrynowicz April 15, 2019, 2:16 p.m.
MSP430 requires NOP instructions to be inserted before some instructions which
enable or disable interrupts.

Currently, the assembler will always act when NOPs are missing around an
instruction which *may* change interrupt state. These are instructions that
modify the status register in a way that is unknown at assembly time e.g.
because the value being written to the status register is in a register.

The attached patch adds options so this behaviour to act on instructions which
*may* enable or disable interrupts can be toggled on/off. The constraints for
when to warn about the "unknown" interrupt state changes have also been
tightened, to prevent extraneous warnings.

If the patch is acceptable, I would appreciate if someone would commit it for
me as I do not have write access.

Thanks,
Jozef

Comments

Jozef Lawrynowicz April 16, 2019, 6:11 p.m. | #1
Missed the ChangeLog in previous submission, now added to attached patch.
Also removed unwanted addition of "md" option to md_shortopts.

On Mon, 15 Apr 2019 15:16:07 +0100
Jozef Lawrynowicz <jozef.l@mittosystems.com> wrote:

> MSP430 requires NOP instructions to be inserted before some instructions which

> enable or disable interrupts.

> 

> Currently, the assembler will always act when NOPs are missing around an

> instruction which *may* change interrupt state. These are instructions that

> modify the status register in a way that is unknown at assembly time e.g.

> because the value being written to the status register is in a register.

> 

> The attached patch adds options so this behaviour to act on instructions which

> *may* enable or disable interrupts can be toggled on/off. The constraints for

> when to warn about the "unknown" interrupt state changes have also been

> tightened, to prevent extraneous warnings.

> 

> If the patch is acceptable, I would appreciate if someone would commit it for

> me as I do not have write access.

> 

> Thanks,

> Jozef
From ed83c5c78e3bb19817c8baeb6fefb95e3a21661e Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>

Date: Fri, 12 Apr 2019 21:58:30 +0100
Subject: [PATCH] Add -m{u,U} options to enable/disable NOP warnings for
 unknown interrupt state changes

gas/ChangeLog:

2019-04-16  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

	* config/tc-msp430.c (options): New OPTION_UNKNOWN_INTR_NOPS,
	OPTION_NO_UNKNOWN_INTR_NOPS and do_unknown_interrupt_nops.
	(md_parse_option): Handle OPTION_UNKNOWN_INTR_NOPS and
	OPTION_NO_UNKNOWN_INTR_NOPS by setting do_unknown_interrupt_nops
	accordingly.
	(md_show_usage): Likewise.
	(md_shortopts): Add "mu" for OPTION_UNKNOWN_INTR_NOPS and
	"mU" for OPTION_NO_UNKNOWN_INTR_NOPS.
	(md_longopts): Likewise.
	(warn_eint_nop): Update comment.
	(warn_unsure_interrupt): Don't warn if prev_insn_is_nop or
	prev_insn_is_dint or we are assembling for 430 ISA.
	(msp430_operands): Only call warn_unsure_interrupt if
	do_unknown_interrupt_nops == TRUE.
	* testsuite/gas/msp430/nop-unknown-intr.s: New test source file.
	* testsuite/gas/msp430/nop-unknown-intr-430.d: New test.
	* testsuite/gas/msp430/nop-unknown-intr-430x.d: New test.
	* testsuite/gas/msp430/nop-unknown-intr-430x-ignore.d: New test.
	* testsuite/gas/msp430/nop-unknown-intr-430.l: Warning output for new
	test.
	* testsuite/gas/msp430/nop-unknown-intr-430x.l: Likewise.
	* testsuite/gas/msp430/msp430.exp: Add new tests to driver.
---
 gas/config/tc-msp430.c                        | 40 +++++++++++++++----
 gas/testsuite/gas/msp430/msp430.exp           |  3 ++
 .../gas/msp430/nop-unknown-intr-430.d         | 15 +++++++
 .../gas/msp430/nop-unknown-intr-430.l         |  3 ++
 .../gas/msp430/nop-unknown-intr-430x-ignore.d | 14 +++++++
 .../gas/msp430/nop-unknown-intr-430x.d        | 15 +++++++
 .../gas/msp430/nop-unknown-intr-430x.l        |  5 +++
 gas/testsuite/gas/msp430/nop-unknown-intr.s   | 16 ++++++++
 8 files changed, 104 insertions(+), 7 deletions(-)
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430.d
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430.l
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430x-ignore.d
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430x.d
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430x.l
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr.s

diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c
index 31bbdbbc81..da3cefde1d 100644
--- a/gas/config/tc-msp430.c
+++ b/gas/config/tc-msp430.c
@@ -680,6 +680,9 @@ static bfd_boolean gen_interrupt_nops = FALSE;
 #define OPTION_WARN_INTR_NOPS 'y'
 #define OPTION_NO_WARN_INTR_NOPS 'Y'
 static bfd_boolean warn_interrupt_nops = TRUE;
+#define OPTION_UNKNOWN_INTR_NOPS 'u'
+#define OPTION_NO_UNKNOWN_INTR_NOPS 'U'
+static bfd_boolean do_unknown_interrupt_nops = TRUE;
 #define OPTION_MCPU 'c'
 #define OPTION_MOVE_DATA 'd'
 static bfd_boolean move_data = FALSE;
@@ -1454,6 +1457,13 @@ md_parse_option (int c, const char * arg)
       warn_interrupt_nops = FALSE;
       return 1;
 
+    case OPTION_UNKNOWN_INTR_NOPS:
+      do_unknown_interrupt_nops = TRUE;
+      return 1;
+    case OPTION_NO_UNKNOWN_INTR_NOPS:
+      do_unknown_interrupt_nops = FALSE;
+      return 1;
+
     case OPTION_MOVE_DATA:
       move_data = TRUE;
       return 1;
@@ -1574,7 +1584,7 @@ const pseudo_typeS md_pseudo_table[] =
   {NULL, NULL, 0}
 };
 
-const char *md_shortopts = "mm:,mP,mQ,ml,mN,mn,my,mY";
+const char *md_shortopts = "mm:,mP,mQ,ml,mN,mn,my,mY,mu,mU";
 
 struct option md_longopts[] =
 {
@@ -1589,6 +1599,8 @@ struct option md_longopts[] =
   {"mn", no_argument, NULL, OPTION_INTR_NOPS},
   {"mY", no_argument, NULL, OPTION_NO_WARN_INTR_NOPS},
   {"my", no_argument, NULL, OPTION_WARN_INTR_NOPS},
+  {"mu", no_argument, NULL, OPTION_UNKNOWN_INTR_NOPS},
+  {"mU", no_argument, NULL, OPTION_NO_UNKNOWN_INTR_NOPS},
   {"md", no_argument, NULL, OPTION_MOVE_DATA},
   {"mdata-region", required_argument, NULL, OPTION_DATA_REGION},
   {NULL, no_argument, NULL, 0}
@@ -1620,6 +1632,13 @@ md_show_usage (FILE * stream)
 	   _("  -mY - do not warn about missing NOPs after changing interrupts\n"));
   fprintf (stream,
 	   _("  -my - warn about missing NOPs after changing interrupts (default)\n"));
+  fprintf (stream,
+	   _("  -mU - for an instruction which changes interrupt state, but where it is not\n"
+	     "        known how the state is changed, do not warn/insert NOPs\n"));
+  fprintf (stream,
+	   _("  -mu - for an instruction which changes interrupt state, but where it is not\n"
+	     "        known how the state is changed, warn/insert NOPs (default)\n"
+	     "        -mn and/or -my are required for this to have any effect\n"));
   fprintf (stream,
 	   _("  -md - Force copying of data from ROM to RAM at startup\n"));
   fprintf (stream,
@@ -2536,7 +2555,8 @@ static void
 warn_eint_nop (bfd_boolean prev_insn_is_nop, bfd_boolean prev_insn_is_dint)
 {
   if (prev_insn_is_nop
-      /* Prevent double warning for DINT immediately before EINT.  */
+      /* If the last insn was a DINT, we will have already warned that a NOP is
+	 required after it.  */
       || prev_insn_is_dint
       /* 430 ISA does not require a NOP before EINT.  */
       || (! target_is_430x ()))
@@ -2554,10 +2574,16 @@ warn_eint_nop (bfd_boolean prev_insn_is_nop, bfd_boolean prev_insn_is_dint)
 /* Use when unsure what effect the insn will have on the interrupt status,
    to insert/warn about adding a NOP before the current insn.  */
 static void
-warn_unsure_interrupt (void)
+warn_unsure_interrupt (bfd_boolean prev_insn_is_nop,
+		       bfd_boolean prev_insn_is_dint)
 {
-  /* Since this could enable or disable interrupts, need to add/warn about
-     adding a NOP before and after this insn.  */
+  if (prev_insn_is_nop
+      /* If the last insn was a DINT, we will have already warned that a NOP is
+	 required after it.  */
+      || prev_insn_is_dint
+      /* 430 ISA does not require a NOP before EINT or DINT.  */
+      || (! target_is_430x ()))
+    return;
   if (gen_interrupt_nops)
     {
       gen_nop ();
@@ -3646,12 +3672,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
 	  else if (op1.mode == OP_REG
 		   && (op1.reg == 2 || op1.reg == 3))
 	    this_insn_is_dint = TRUE;
-	  else
+	  else if (do_unknown_interrupt_nops)
 	    {
 	      /* FIXME: Couldn't work out whether the insn is enabling or
 		 disabling interrupts, so for safety need to treat it as both
 		 a DINT and EINT.  */
-	      warn_unsure_interrupt ();
+	      warn_unsure_interrupt (prev_insn_is_nop, prev_insn_is_dint);
 	      check_for_nop |= NOP_CHECK_INTERRUPT;
 	    }
 	}
diff --git a/gas/testsuite/gas/msp430/msp430.exp b/gas/testsuite/gas/msp430/msp430.exp
index 6d02d2a9f7..686e7618f5 100644
--- a/gas/testsuite/gas/msp430/msp430.exp
+++ b/gas/testsuite/gas/msp430/msp430.exp
@@ -38,4 +38,7 @@ if [expr [istarget "msp430-*-*"]]  then {
     run_dump_test "nop-dint-430x"
     run_dump_test "nop-dint-430x-silent"
     run_dump_test "nop-dint-430x-ignore"
+    run_dump_test "nop-unknown-intr-430"
+    run_dump_test "nop-unknown-intr-430x"
+    run_dump_test "nop-unknown-intr-430x-ignore"
 }
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430.d b/gas/testsuite/gas/msp430/nop-unknown-intr-430.d
new file mode 100644
index 0000000000..20aa4db230
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430.d
@@ -0,0 +1,14 @@
+#name: Unknown Interrupt State NOP Insertions (MSP430 CPU)
+#source: nop-unknown-intr.s
+#as: -my -mu -mcpu=430
+#warning_output: nop-unknown-intr-430.l
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+
+Disassembly of section .text:
+0x0+0000 12 42 00 00[ 	]+mov[ 	]+&0x0000,r2[ 	]+;0x0000
+0x0+0004 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
+0x0+0008 02 47[ 	]+mov[ 	]+r7,[ 	]+r2[ 	]+;
+0x0+000a 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430.l b/gas/testsuite/gas/msp430/nop-unknown-intr-430.l
new file mode 100644
index 0000000000..9727572d44
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430.l
@@ -0,0 +1,3 @@
+[^:]*: Assembler messages:
+[^:]*:11: Warning: a NOP might also be needed here, after the instruction that changed interrupt state
+[^:]*:16: Warning: a NOP might also be needed here, after the instruction that changed interrupt state
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430x-ignore.d b/gas/testsuite/gas/msp430/nop-unknown-intr-430x-ignore.d
new file mode 100644
index 0000000000..c04b5048ad
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430x-ignore.d
@@ -0,0 +1,13 @@
+#name: Ignore Unknown Interrupt State NOP Insertions (MSP430X CPU)
+#source: nop-unknown-intr.s
+#as: -my -mU -mcpu=430x
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+
+Disassembly of section .text:
+0x0+0000 12 42 00 00[ 	]+mov[ 	]+&0x0000,r2[ 	]+;0x0000
+0x0+0004 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
+0x0+0008 02 47[ 	]+mov[ 	]+r7,[ 	]+r2[ 	]+;
+0x0+000a 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430x.d b/gas/testsuite/gas/msp430/nop-unknown-intr-430x.d
new file mode 100644
index 0000000000..208b299045
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430x.d
@@ -0,0 +1,14 @@
+#name: Unknown Interrupt State NOP Insertions (MSP430X CPU)
+#source: nop-unknown-intr.s
+#as: -my -mu -mcpu=430x
+#warning_output: nop-unknown-intr-430x.l
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+
+Disassembly of section .text:
+0x0+0000 12 42 00 00[ 	]+mov[ 	]+&0x0000,r2[ 	]+;0x0000
+0x0+0004 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
+0x0+0008 02 47[ 	]+mov[ 	]+r7,[ 	]+r2[ 	]+;
+0x0+000a 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430x.l b/gas/testsuite/gas/msp430/nop-unknown-intr-430x.l
new file mode 100644
index 0000000000..af27c2ba13
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430x.l
@@ -0,0 +1,5 @@
+[^:]*: Assembler messages:
+[^:]*:9: Warning: a NOP might be needed here, before this interrupt state change
+[^:]*:11: Warning: a NOP might also be needed here, after the instruction that changed interrupt state
+[^:]*:14: Warning: a NOP might be needed here, before this interrupt state change
+[^:]*:16: Warning: a NOP might also be needed here, after the instruction that changed interrupt state
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr.s b/gas/testsuite/gas/msp430/nop-unknown-intr.s
new file mode 100644
index 0000000000..df21b6e80b
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr.s
@@ -0,0 +1,16 @@
+	.text
+
+;;; Test for warnings when an instruction might change interrupt state, but
+;;; the assembler doesn't know whether interrupts will be enabled or disabled.
+;;; "MOV &FOO,R10" is used as an artbitrary statement which isn't a NOP, to
+;;; break up the instructions being tested.
+
+;;; Moving a value in memory into SR might change interrupt state
+	MOV &FOO,R2
+
+	MOV &FOO,R10
+
+;;; Moving a value from a register into SR might change interrupt state
+	MOV R7,R2
+
+	MOV &FOO,R10
-- 
2.17.1
Nick Clifton April 17, 2019, 2:06 p.m. | #2
Hi Jozef,

>> Currently, the assembler will always act when NOPs are missing around an

>> instruction which *may* change interrupt state. These are instructions that

>> modify the status register in a way that is unknown at assembly time e.g.

>> because the value being written to the status register is in a register.

>>

>> The attached patch adds options so this behaviour to act on instructions which

>> *may* enable or disable interrupts can be toggled on/off. The constraints for

>> when to warn about the "unknown" interrupt state changes have also been

>> tightened, to prevent extraneous warnings.

>>

>> If the patch is acceptable, I would appreciate if someone would commit it for

>> me as I do not have write access.


Approved and applied.

Cheers
  Nick

Patch

From 03af8fc1e6ca3d355844ca212c0a37c8d1a37ebf Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Fri, 12 Apr 2019 21:58:30 +0100
Subject: [PATCH] [MSP430] Add -m{u,U} options to enable/disable NOP warnings
 for unknown interrupt state changes

---
 gas/config/tc-msp430.c                        | 40 +++++++++++++++----
 gas/testsuite/gas/msp430/msp430.exp           |  3 ++
 .../gas/msp430/nop-unknown-intr-430.d         | 15 +++++++
 .../gas/msp430/nop-unknown-intr-430.l         |  3 ++
 .../gas/msp430/nop-unknown-intr-430x-ignore.d | 14 +++++++
 .../gas/msp430/nop-unknown-intr-430x.d        | 15 +++++++
 .../gas/msp430/nop-unknown-intr-430x.l        |  5 +++
 gas/testsuite/gas/msp430/nop-unknown-intr.s   | 16 ++++++++
 8 files changed, 104 insertions(+), 7 deletions(-)
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430.d
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430.l
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430x-ignore.d
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430x.d
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr-430x.l
 create mode 100644 gas/testsuite/gas/msp430/nop-unknown-intr.s

diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c
index 31bbdbbc81..9743fc3be2 100644
--- a/gas/config/tc-msp430.c
+++ b/gas/config/tc-msp430.c
@@ -680,6 +680,9 @@  static bfd_boolean gen_interrupt_nops = FALSE;
 #define OPTION_WARN_INTR_NOPS 'y'
 #define OPTION_NO_WARN_INTR_NOPS 'Y'
 static bfd_boolean warn_interrupt_nops = TRUE;
+#define OPTION_UNKNOWN_INTR_NOPS 'u'
+#define OPTION_NO_UNKNOWN_INTR_NOPS 'U'
+static bfd_boolean do_unknown_interrupt_nops = TRUE;
 #define OPTION_MCPU 'c'
 #define OPTION_MOVE_DATA 'd'
 static bfd_boolean move_data = FALSE;
@@ -1454,6 +1457,13 @@  md_parse_option (int c, const char * arg)
       warn_interrupt_nops = FALSE;
       return 1;
 
+    case OPTION_UNKNOWN_INTR_NOPS:
+      do_unknown_interrupt_nops = TRUE;
+      return 1;
+    case OPTION_NO_UNKNOWN_INTR_NOPS:
+      do_unknown_interrupt_nops = FALSE;
+      return 1;
+
     case OPTION_MOVE_DATA:
       move_data = TRUE;
       return 1;
@@ -1574,7 +1584,7 @@  const pseudo_typeS md_pseudo_table[] =
   {NULL, NULL, 0}
 };
 
-const char *md_shortopts = "mm:,mP,mQ,ml,mN,mn,my,mY";
+const char *md_shortopts = "mm:,mP,mQ,ml,mN,mn,my,mY,mu,mU,md";
 
 struct option md_longopts[] =
 {
@@ -1589,6 +1599,8 @@  struct option md_longopts[] =
   {"mn", no_argument, NULL, OPTION_INTR_NOPS},
   {"mY", no_argument, NULL, OPTION_NO_WARN_INTR_NOPS},
   {"my", no_argument, NULL, OPTION_WARN_INTR_NOPS},
+  {"mu", no_argument, NULL, OPTION_UNKNOWN_INTR_NOPS},
+  {"mU", no_argument, NULL, OPTION_NO_UNKNOWN_INTR_NOPS},
   {"md", no_argument, NULL, OPTION_MOVE_DATA},
   {"mdata-region", required_argument, NULL, OPTION_DATA_REGION},
   {NULL, no_argument, NULL, 0}
@@ -1620,6 +1632,13 @@  md_show_usage (FILE * stream)
 	   _("  -mY - do not warn about missing NOPs after changing interrupts\n"));
   fprintf (stream,
 	   _("  -my - warn about missing NOPs after changing interrupts (default)\n"));
+  fprintf (stream,
+	   _("  -mU - for an instruction which changes interrupt state, but where it is not\n"
+	     "        known how the state is changed, do not warn/insert NOPs\n"));
+  fprintf (stream,
+	   _("  -mu - for an instruction which changes interrupt state, but where it is not\n"
+	     "        known how the state is changed, warn/insert NOPs (default)\n"
+	     "        -mn and/or -my are required for this to have any effect\n"));
   fprintf (stream,
 	   _("  -md - Force copying of data from ROM to RAM at startup\n"));
   fprintf (stream,
@@ -2536,7 +2555,8 @@  static void
 warn_eint_nop (bfd_boolean prev_insn_is_nop, bfd_boolean prev_insn_is_dint)
 {
   if (prev_insn_is_nop
-      /* Prevent double warning for DINT immediately before EINT.  */
+      /* If the last insn was a DINT, we will have already warned that a NOP is
+	 required after it.  */
       || prev_insn_is_dint
       /* 430 ISA does not require a NOP before EINT.  */
       || (! target_is_430x ()))
@@ -2554,10 +2574,16 @@  warn_eint_nop (bfd_boolean prev_insn_is_nop, bfd_boolean prev_insn_is_dint)
 /* Use when unsure what effect the insn will have on the interrupt status,
    to insert/warn about adding a NOP before the current insn.  */
 static void
-warn_unsure_interrupt (void)
+warn_unsure_interrupt (bfd_boolean prev_insn_is_nop,
+		       bfd_boolean prev_insn_is_dint)
 {
-  /* Since this could enable or disable interrupts, need to add/warn about
-     adding a NOP before and after this insn.  */
+  if (prev_insn_is_nop
+      /* If the last insn was a DINT, we will have already warned that a NOP is
+	 required after it.  */
+      || prev_insn_is_dint
+      /* 430 ISA does not require a NOP before EINT or DINT.  */
+      || (! target_is_430x ()))
+    return;
   if (gen_interrupt_nops)
     {
       gen_nop ();
@@ -3646,12 +3672,12 @@  msp430_operands (struct msp430_opcode_s * opcode, char * line)
 	  else if (op1.mode == OP_REG
 		   && (op1.reg == 2 || op1.reg == 3))
 	    this_insn_is_dint = TRUE;
-	  else
+	  else if (do_unknown_interrupt_nops)
 	    {
 	      /* FIXME: Couldn't work out whether the insn is enabling or
 		 disabling interrupts, so for safety need to treat it as both
 		 a DINT and EINT.  */
-	      warn_unsure_interrupt ();
+	      warn_unsure_interrupt (prev_insn_is_nop, prev_insn_is_dint);
 	      check_for_nop |= NOP_CHECK_INTERRUPT;
 	    }
 	}
diff --git a/gas/testsuite/gas/msp430/msp430.exp b/gas/testsuite/gas/msp430/msp430.exp
index 6d02d2a9f7..686e7618f5 100644
--- a/gas/testsuite/gas/msp430/msp430.exp
+++ b/gas/testsuite/gas/msp430/msp430.exp
@@ -38,4 +38,7 @@  if [expr [istarget "msp430-*-*"]]  then {
     run_dump_test "nop-dint-430x"
     run_dump_test "nop-dint-430x-silent"
     run_dump_test "nop-dint-430x-ignore"
+    run_dump_test "nop-unknown-intr-430"
+    run_dump_test "nop-unknown-intr-430x"
+    run_dump_test "nop-unknown-intr-430x-ignore"
 }
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430.d b/gas/testsuite/gas/msp430/nop-unknown-intr-430.d
new file mode 100644
index 0000000000..20aa4db230
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430.d
@@ -0,0 +1,15 @@ 
+#name: Unknown Interrupt State NOP Insertions (MSP430 CPU)
+#source: nop-unknown-intr.s
+#as: -my -mu -mcpu=430
+#warning_output: nop-unknown-intr-430.l
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+
+Disassembly of section .text:
+0x0+0000 12 42 00 00[ 	]+mov[ 	]+&0x0000,r2[ 	]+;0x0000
+0x0+0004 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
+0x0+0008 02 47[ 	]+mov[ 	]+r7,[ 	]+r2[ 	]+;
+0x0+000a 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
+
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430.l b/gas/testsuite/gas/msp430/nop-unknown-intr-430.l
new file mode 100644
index 0000000000..9727572d44
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430.l
@@ -0,0 +1,3 @@ 
+[^:]*: Assembler messages:
+[^:]*:11: Warning: a NOP might also be needed here, after the instruction that changed interrupt state
+[^:]*:16: Warning: a NOP might also be needed here, after the instruction that changed interrupt state
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430x-ignore.d b/gas/testsuite/gas/msp430/nop-unknown-intr-430x-ignore.d
new file mode 100644
index 0000000000..c04b5048ad
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430x-ignore.d
@@ -0,0 +1,14 @@ 
+#name: Ignore Unknown Interrupt State NOP Insertions (MSP430X CPU)
+#source: nop-unknown-intr.s
+#as: -my -mU -mcpu=430x
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+
+Disassembly of section .text:
+0x0+0000 12 42 00 00[ 	]+mov[ 	]+&0x0000,r2[ 	]+;0x0000
+0x0+0004 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
+0x0+0008 02 47[ 	]+mov[ 	]+r7,[ 	]+r2[ 	]+;
+0x0+000a 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
+
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430x.d b/gas/testsuite/gas/msp430/nop-unknown-intr-430x.d
new file mode 100644
index 0000000000..208b299045
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430x.d
@@ -0,0 +1,15 @@ 
+#name: Unknown Interrupt State NOP Insertions (MSP430X CPU)
+#source: nop-unknown-intr.s
+#as: -my -mu -mcpu=430x
+#warning_output: nop-unknown-intr-430x.l
+#objdump: -d --prefix-addresses --show-raw-insn
+
+.*: +file format .*msp.*
+
+
+Disassembly of section .text:
+0x0+0000 12 42 00 00[ 	]+mov[ 	]+&0x0000,r2[ 	]+;0x0000
+0x0+0004 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
+0x0+0008 02 47[ 	]+mov[ 	]+r7,[ 	]+r2[ 	]+;
+0x0+000a 1a 42 00 00[ 	]+mov[ 	]+&0x0000,r10[ 	]+;0x0000
+
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr-430x.l b/gas/testsuite/gas/msp430/nop-unknown-intr-430x.l
new file mode 100644
index 0000000000..af27c2ba13
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr-430x.l
@@ -0,0 +1,5 @@ 
+[^:]*: Assembler messages:
+[^:]*:9: Warning: a NOP might be needed here, before this interrupt state change
+[^:]*:11: Warning: a NOP might also be needed here, after the instruction that changed interrupt state
+[^:]*:14: Warning: a NOP might be needed here, before this interrupt state change
+[^:]*:16: Warning: a NOP might also be needed here, after the instruction that changed interrupt state
diff --git a/gas/testsuite/gas/msp430/nop-unknown-intr.s b/gas/testsuite/gas/msp430/nop-unknown-intr.s
new file mode 100644
index 0000000000..df21b6e80b
--- /dev/null
+++ b/gas/testsuite/gas/msp430/nop-unknown-intr.s
@@ -0,0 +1,16 @@ 
+	.text
+
+;;; Test for warnings when an instruction might change interrupt state, but
+;;; the assembler doesn't know whether interrupts will be enabled or disabled.
+;;; "MOV &FOO,R10" is used as an artbitrary statement which isn't a NOP, to
+;;; break up the instructions being tested.
+
+;;; Moving a value in memory into SR might change interrupt state
+	MOV &FOO,R2
+
+	MOV &FOO,R10
+
+;;; Moving a value from a register into SR might change interrupt state
+	MOV R7,R2
+
+	MOV &FOO,R10
-- 
2.17.1