From d557977487bc21e8ed19603527949a8541c44832 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Wed, 17 Apr 2019 15:01:28 +0100 Subject: [PATCH] MSP420 assembler: Add -m{u,U} options to enable/disable NOP warnings for unknown interrupt state changes gas * 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/ChangeLog | 25 +++++++++++ gas/config/tc-msp430.c | 45 +++++++++++++++---- .../gas/msp430/either-data-bss-sym.d | 9 ++++ .../gas/msp430/either-data-bss-sym.s | 24 ++++++++++ gas/testsuite/gas/msp430/low-data-bss-sym.d | 7 +++ gas/testsuite/gas/msp430/low-data-bss-sym.s | 24 ++++++++++ gas/testsuite/gas/msp430/msp430.exp | 9 +++- .../gas/msp430/nop-unknown-intr-430.d | 14 ++++++ .../gas/msp430/nop-unknown-intr-430.l | 3 ++ .../gas/msp430/nop-unknown-intr-430x-ignore.d | 13 ++++++ .../gas/msp430/nop-unknown-intr-430x.d | 14 ++++++ .../gas/msp430/nop-unknown-intr-430x.l | 5 +++ gas/testsuite/gas/msp430/nop-unknown-intr.s | 16 +++++++ 13 files changed, 198 insertions(+), 10 deletions(-) create mode 100644 gas/testsuite/gas/msp430/either-data-bss-sym.d create mode 100644 gas/testsuite/gas/msp430/either-data-bss-sym.s create mode 100644 gas/testsuite/gas/msp430/low-data-bss-sym.d create mode 100644 gas/testsuite/gas/msp430/low-data-bss-sym.s 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/ChangeLog b/gas/ChangeLog index 91b2322b7d..d6c80cb45e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,28 @@ +2019-04-17 Jozef Lawrynowicz + + * 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. + 2019-04-16 Alan Modra * testsuite/gas/all/weakref1.d: xfail nds32. diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c index 31bbdbbc81..7868331bb9 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; @@ -1484,13 +1494,16 @@ static void msp430_make_init_symbols (const char * name) { if (strncmp (name, ".bss", 4) == 0 + || strncmp (name, ".lower.bss", 10) == 0 + || strncmp (name, ".either.bss", 11) == 0 || strncmp (name, ".gnu.linkonce.b.", 16) == 0) (void) symbol_find_or_make ("__crt0_init_bss"); if (strncmp (name, ".data", 5) == 0 + || strncmp (name, ".lower.data", 11) == 0 + || strncmp (name, ".either.data", 12) == 0 || strncmp (name, ".gnu.linkonce.d.", 16) == 0) (void) symbol_find_or_make ("__crt0_movedata"); - /* Note - data assigned to the .either.data section may end up being placed in the .upper.data section if the .lower.data section is full. Hence the need to define the crt0 symbol. @@ -1574,7 +1587,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 +1602,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 +1635,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 +2558,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 +2577,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 +3675,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/either-data-bss-sym.d b/gas/testsuite/gas/msp430/either-data-bss-sym.d new file mode 100644 index 0000000000..9e4154fe95 --- /dev/null +++ b/gas/testsuite/gas/msp430/either-data-bss-sym.d @@ -0,0 +1,9 @@ +#objdump: -t +#name: Check symbols to initialise data and bss have been defined for .either sections +#... +.*__crt0_movedata.* +.*__crt0_move_highdata.* +#... +.*__crt0_init_bss.* +.*__crt0_init_highbss.* +#pass diff --git a/gas/testsuite/gas/msp430/either-data-bss-sym.s b/gas/testsuite/gas/msp430/either-data-bss-sym.s new file mode 100644 index 0000000000..c847d9e2ce --- /dev/null +++ b/gas/testsuite/gas/msp430/either-data-bss-sym.s @@ -0,0 +1,24 @@ + .file "main.c" +.text + .global a + .section .either.data,"aw" + .balign 2 + .type a, @object + .size a, 2 +a: + .short 42 + .global b + .section .either.bss,"aw",@nobits + .balign 2 + .type b, @object + .size b, 2 +b: + .zero 2 +.text + .balign 2 + .global main + .type main, @function +main: +.L2: + BR #.L2 + .size main, .-main diff --git a/gas/testsuite/gas/msp430/low-data-bss-sym.d b/gas/testsuite/gas/msp430/low-data-bss-sym.d new file mode 100644 index 0000000000..0ed57c6d69 --- /dev/null +++ b/gas/testsuite/gas/msp430/low-data-bss-sym.d @@ -0,0 +1,7 @@ +#objdump: -t +#name: Check symbols to initialise data and bss have been defined for .lower sections +#... +.*__crt0_movedata.* +#... +.*__crt0_init_bss.* +#pass diff --git a/gas/testsuite/gas/msp430/low-data-bss-sym.s b/gas/testsuite/gas/msp430/low-data-bss-sym.s new file mode 100644 index 0000000000..317fb175a1 --- /dev/null +++ b/gas/testsuite/gas/msp430/low-data-bss-sym.s @@ -0,0 +1,24 @@ + .file "main.c" +.text + .global a + .section .lower.data,"aw" + .balign 2 + .type a, @object + .size a, 2 +a: + .short 42 + .global b + .section .lower.bss,"aw",@nobits + .balign 2 + .type b, @object + .size b, 2 +b: + .zero 2 +.text + .balign 2 + .global main + .type main, @function +main: +.L2: + BR #.L2 + .size main, .-main diff --git a/gas/testsuite/gas/msp430/msp430.exp b/gas/testsuite/gas/msp430/msp430.exp index 6d02d2a9f7..0f7805da3e 100644 --- a/gas/testsuite/gas/msp430/msp430.exp +++ b/gas/testsuite/gas/msp430/msp430.exp @@ -24,8 +24,10 @@ if [expr [istarget "msp430-*-*"]] then { run_dump_test "bad" run_dump_test "errata_warns" run_dump_test "errata_fixes" - 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 "low-data-bss-sym" + run_dump_test "either-data-bss-sym" + run_dump_test "high-data-bss-sym" { { as "-ml -mdata-region=upper" } } + run_dump_test "high-data-bss-sym" { { as "-ml -mdata-region=either" } } run_dump_test "pr22133" run_dump_test "nop-int-430" run_dump_test "nop-int-430x" @@ -38,4 +40,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..ac75f6c318 --- /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..6c2f36adb9 --- /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..8141bd52a5 --- /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.34.1