diff options
author | Jozef Lawrynowicz <jozef.l@mittosystems.com> | 2019-04-17 15:01:28 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2019-04-17 15:01:28 +0100 |
commit | d557977487bc21e8ed19603527949a8541c44832 (patch) | |
tree | 66864e66dc2eeca1c8ede8ac95232b39b3533f57 /gas/config | |
parent | a12e57448ecf2644e3ddc98bbd4bbb914a5f8c92 (diff) | |
download | gdb-d557977487bc21e8ed19603527949a8541c44832.zip gdb-d557977487bc21e8ed19603527949a8541c44832.tar.gz gdb-d557977487bc21e8ed19603527949a8541c44832.tar.bz2 |
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.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-msp430.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c index 31bbdbb..7868331 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} @@ -1621,6 +1636,13 @@ md_show_usage (FILE * stream) 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, _(" -mdata-region={none|lower|upper|either} - select region data will be\n" @@ -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; } } |