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.
This commit is contained in:
Jozef Lawrynowicz 2018-11-27 12:25:09 +00:00 committed by Nick Clifton
parent 4207142d6a
commit 35ba4bc019
24 changed files with 751 additions and 71 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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"
}

View File

@ -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[ ]+

View File

@ -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

View File

@ -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.*
#...

View File

@ -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[ ]+

View File

@ -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[ ]+

View File

@ -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

View File

@ -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

View File

@ -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[ ]+

View File

@ -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

View File

@ -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.*
#...

View File

@ -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[ ]+

View File

@ -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[ ]+

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,4 @@
#name: Interrupt NOP Warnings (MSP430 CPU)
#source: nop-int.s
#as: -my -mcpu=430
#warning_output: nop-int-430.l

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,4 @@
#name: Interrupt NOP Warnings (MSP430X CPU)
#source: nop-int.s
#as: -my -mcpu=430x
#warning_output: nop-int-430x.l

View File

@ -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

View File

@ -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