From 927f2d25ef9d9dc35d6a4061d5504b0fc928f057 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 6 Apr 2016 15:57:19 +0100 Subject: [PATCH] Fix MSP430 assembler's detection of NOP and EINT. * config/tc-msp430.c (msp430_operands): Check for a NOP preceding an EINT instruction. Warn/fix as necessary. * testsuite/gas/msp430/bad.s: Add test of EINT without preceding NOP. * testsuite/gas/msp430/bad.l: Update expected messages. --- gas/ChangeLog | 7 +++++++ gas/config/tc-msp430.c | 25 ++++++++++++++++++++++++- gas/testsuite/gas/msp430/bad.l | 14 ++++++++------ gas/testsuite/gas/msp430/bad.s | 6 ++++++ 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index ec9c4e2cfbd..8647d9e6b6d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2016-04-06 Nick Clifton + + * config/tc-msp430.c (msp430_operands): Check for a NOP preceding + an EINT instruction. Warn/fix as necessary. + * testsuite/gas/msp430/bad.s: Add test of EINT without preceding NOP. + * testsuite/gas/msp430/bad.l: Update expected messages. + 2016-04-05 Andrew Burgess * testsuite/gas/arc/nps400-1.d: Update expected results. diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c index 817ab452cac..f9df7290f5e 100644 --- a/gas/config/tc-msp430.c +++ b/gas/config/tc-msp430.c @@ -2471,6 +2471,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) bfd_boolean addr_op; const char * error_message; static signed int repeat_count = 0; + static bfd_boolean prev_insn_is_nop = FALSE; bfd_boolean fix_emitted; /* Opcode is the one from opcodes table @@ -2670,7 +2671,24 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) switch (opcode->insn_opnumb) { case 0: - if (is_opcode ("eint") || is_opcode ("dint")) + 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; /* Set/clear bits instructions. */ @@ -3857,6 +3875,11 @@ 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; + input_line_pointer = line; return 0; } diff --git a/gas/testsuite/gas/msp430/bad.l b/gas/testsuite/gas/msp430/bad.l index 6cc3e3a299d..f4665133920 100644 --- a/gas/testsuite/gas/msp430/bad.l +++ b/gas/testsuite/gas/msp430/bad.l @@ -5,11 +5,13 @@ [^:]*:9: Error: junk found after instruction: mov.cd r1,r2 [^:]*:10: Warning: no size modifier after period, .w assumed [^:]*:11: Error: instruction bis.a does not exist -[^:]*:19: Warning: a NOP might be needed here because of successive changes in interrupt state -[^:]*:20: Warning: a NOP might be needed here because of successive changes in interrupt state -[^:]*:23: Warning: a NOP might be needed here because of successive changes in interrupt state +[^:]*: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 -[^:]*:26: Warning: a NOP might be needed here because of successive changes in interrupt state -[^:]*:27: Warning: a NOP might be needed here because of successive changes in interrupt state -[^:]*:28: Warning: a NOP might be needed here because of successive changes in interrupt state +[^:]*: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 diff --git a/gas/testsuite/gas/msp430/bad.s b/gas/testsuite/gas/msp430/bad.s index b9c4af2e308..ae2db2f01cd 100644 --- a/gas/testsuite/gas/msp430/bad.s +++ b/gas/testsuite/gas/msp430/bad.s @@ -11,6 +11,12 @@ bis.a #8, r2 ;;; FIXME: Add more tests of assembler error detection here. + + ;; A NOP is needed *before* an EINT instruction. + eint + nop + ;; And *after* a DINT instruction. + dint ;; Changing interrupt states in two successive instructions ;; might cause an interrupt to be missed. The assembler -- 2.30.2