From 2213f746d3ab63715c24c3197ae207486464091b Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 22 Oct 2015 16:25:46 +0100 Subject: [PATCH] Add support for MSP430 silicon errata to the assembler. * config/tc-msp430.c (PUSH_1X_WORKAROUND): Delete. (OPTION_SILICON_ERRATA): Define. (OPTION_SILICON_WARN): Define. (md_parse_opton): Handle silicon errata options. (md_longopts): Add silicon errata options. (ms_show_usage): Report silicon errata options. (msp430_srcoperand): Handle silicon errata. (msp430_operands): Likewise. Improve nop insertion. (msp430_fix_adjustable): Update warning generation. * doc/c-msp430.texi: Document silicon errata options. tests * gas/msp430/errata_fixes.s: New test source file. * gas/msp430/errata_fixes.d: New test control file. * gas/msp430/errata_warns.s: New test source file. * gas/msp430/errata_warns.d: New test control file. * gas/msp430/errata_warns.l: New test message file. * gas/msp430/msp430.exp: Run the new tests. * gas/msp430/bad.l: Update expected warning messages * gas/msp430/msp430.exp: Run the new tests. --- gas/ChangeLog | 13 + gas/config/tc-msp430.c | 336 ++++++++++++++++++------ gas/doc/c-msp430.texi | 34 +++ gas/testsuite/ChangeLog | 11 + gas/testsuite/gas/msp430/bad.l | 3 +- gas/testsuite/gas/msp430/errata_fixes.d | 23 ++ gas/testsuite/gas/msp430/errata_fixes.s | 24 ++ gas/testsuite/gas/msp430/errata_warns.d | 4 + gas/testsuite/gas/msp430/errata_warns.l | 44 ++++ gas/testsuite/gas/msp430/errata_warns.s | 59 +++++ gas/testsuite/gas/msp430/msp430.exp | 2 + 11 files changed, 473 insertions(+), 80 deletions(-) create mode 100644 gas/testsuite/gas/msp430/errata_fixes.d create mode 100644 gas/testsuite/gas/msp430/errata_fixes.s create mode 100644 gas/testsuite/gas/msp430/errata_warns.d create mode 100644 gas/testsuite/gas/msp430/errata_warns.l create mode 100644 gas/testsuite/gas/msp430/errata_warns.s diff --git a/gas/ChangeLog b/gas/ChangeLog index 0743ff30ee0..1b77b64ba01 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,16 @@ +2015-10-22 Nick Clifton + + * config/tc-msp430.c (PUSH_1X_WORKAROUND): Delete. + (OPTION_SILICON_ERRATA): Define. + (OPTION_SILICON_WARN): Define. + (md_parse_opton): Handle silicon errata options. + (md_longopts): Add silicon errata options. + (ms_show_usage): Report silicon errata options. + (msp430_srcoperand): Handle silicon errata. + (msp430_operands): Likewise. Improve nop insertion. + (msp430_fix_adjustable): Update warning generation. + * doc/c-msp430.texi: Document silicon errata options. + 2015-10-22 H.J. Lu * configure.ac: Properly check diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c index accc5923c8e..8e32189ef8e 100644 --- a/gas/config/tc-msp430.c +++ b/gas/config/tc-msp430.c @@ -22,7 +22,6 @@ #include "as.h" #include -#define PUSH_1X_WORKAROUND #include "subsegs.h" #include "opcode/msp430.h" #include "safe-ctype.h" @@ -681,6 +680,23 @@ static bfd_boolean warn_interrupt_nops = TRUE; #define OPTION_MOVE_DATA 'd' static bfd_boolean move_data = FALSE; +enum +{ + OPTION_SILICON_ERRATA = OPTION_MD_BASE, + OPTION_SILICON_ERRATA_WARN, +} option_numbers; + +static unsigned int silicon_errata_fix = 0; +static unsigned int silicon_errata_warn = 0; +#define SILICON_ERRATA_CPU4 (1 << 0) +#define SILICON_ERRATA_CPU8 (1 << 1) +#define SILICON_ERRATA_CPU11 (1 << 2) +#define SILICON_ERRATA_CPU12 (1 << 3) +#define SILICON_ERRATA_CPU13 (1 << 4) +#define SILICON_ERRATA_CPU19 (1 << 5) +#define SILICON_ERRATA_CPU42 (1 << 6) +#define SILICON_ERRATA_CPU42_PLUS (1 << 7) + static void msp430_set_arch (int option) { @@ -1305,6 +1321,55 @@ md_parse_option (int c, char * arg) { switch (c) { + case OPTION_SILICON_ERRATA: + case OPTION_SILICON_ERRATA_WARN: + { + signed int i; + const struct + { + char * name; + unsigned int length; + unsigned int bitfield; + } erratas[] = + { + { STRING_COMMA_LEN ("cpu4"), SILICON_ERRATA_CPU4 }, + { STRING_COMMA_LEN ("cpu8"), SILICON_ERRATA_CPU8 }, + { STRING_COMMA_LEN ("cpu11"), SILICON_ERRATA_CPU11 }, + { STRING_COMMA_LEN ("cpu12"), SILICON_ERRATA_CPU12 }, + { STRING_COMMA_LEN ("cpu13"), SILICON_ERRATA_CPU13 }, + { STRING_COMMA_LEN ("cpu19"), SILICON_ERRATA_CPU19 }, + { STRING_COMMA_LEN ("cpu42"), SILICON_ERRATA_CPU42 }, + { STRING_COMMA_LEN ("cpu42+"), SILICON_ERRATA_CPU42_PLUS }, + }; + + do + { + for (i = ARRAY_SIZE (erratas); i--;) + if (strncasecmp (arg, erratas[i].name, erratas[i].length) == 0) + { + if (c == OPTION_SILICON_ERRATA) + silicon_errata_fix |= erratas[i].bitfield; + else + silicon_errata_warn |= erratas[i].bitfield; + arg += erratas[i].length; + break; + } + if (i < 0) + { + as_warn (_("Unrecognised CPU errata name starting here: %s"), arg); + break; + } + if (*arg == 0) + break; + if (*arg != ',') + as_warn (_("Expecting comma after CPU errata name, not: %s"), arg); + else + arg ++; + } + while (*arg != 0); + } + return 1; + case OPTION_MMCU: if (arg == NULL) as_fatal (_("MCU option requires a name\n")); @@ -1487,6 +1552,8 @@ const char *md_shortopts = "mm:,mP,mQ,ml,mN,mn,my,mY"; struct option md_longopts[] = { + {"msilicon-errata", required_argument, NULL, OPTION_SILICON_ERRATA}, + {"msilicon-errata-warn", required_argument, NULL, OPTION_SILICON_ERRATA_WARN}, {"mmcu", required_argument, NULL, OPTION_MMCU}, {"mcpu", required_argument, NULL, OPTION_MCPU}, {"mP", no_argument, NULL, OPTION_POLYMORPHS}, @@ -1509,6 +1576,10 @@ md_show_usage (FILE * stream) _("MSP430 options:\n" " -mmcu= - select microcontroller type\n" " -mcpu={430|430x|430xv2} - select microcontroller architecture\n")); + fprintf (stream, + _(" -msilicon-errata=[,...] - enable fixups for silicon errata\n" + " -msilicon-errata-warn=[,...] - warn when a fixup might be needed\n" + " supported errata names: cpu4, cpu8, cpu11, cpu12, cpu13, cpu19, cpu42, cpu42+\n")); fprintf (stream, _(" -mQ - enable relaxation at assembly time. DANGEROUS!\n" " -mP - enable polymorph instructions\n")); @@ -1746,14 +1817,14 @@ msp430_srcoperand (struct msp430_operand_s * op, } else if (x == 4) { -#ifdef PUSH_1X_WORKAROUND - if (bin == 0x1200) + if (bin == 0x1200 && ! target_is_430x ()) { - /* Remove warning as confusing. - as_warn (_("Hardware push bug workaround")); */ + /* CPU4: The shorter form of PUSH #4 is not supported on MSP430. */ + if (silicon_errata_warn & SILICON_ERRATA_CPU4) + as_warn (_("cpu4: not converting PUSH #4 to shorter form")); + /* No need to check silicon_errata_fixes - this fix is always implemented. */ } else -#endif { op->reg = 2; op->am = 2; @@ -1763,14 +1834,13 @@ msp430_srcoperand (struct msp430_operand_s * op, } else if (x == 8) { -#ifdef PUSH_1X_WORKAROUND - if (bin == 0x1200) + if (bin == 0x1200 && ! target_is_430x ()) { - /* Remove warning as confusing. - as_warn (_("Hardware push bug workaround")); */ + /* CPU4: The shorter form of PUSH #8 is not supported on MSP430. */ + if (silicon_errata_warn & SILICON_ERRATA_CPU4) + as_warn (_("cpu4: not converting PUSH #8 to shorter form")); } else -#endif { op->reg = 2; op->am = 3; @@ -2003,6 +2073,14 @@ msp430_srcoperand (struct msp430_operand_s * op, op->ol = 0; return 0; } + + if (op->reg == 1 && (x & 1)) + { + if (silicon_errata_fix & SILICON_ERRATA_CPU8) + as_bad (_("CPU8: Stack pointer accessed with an odd offset")); + else if (silicon_errata_warn & SILICON_ERRATA_CPU8) + as_warn (_("CPU8: Stack pointer accessed with an odd offset")); + } } else if (op->exp.X_op == O_symbol) ; @@ -2353,7 +2431,11 @@ try_encode_mova (bfd_boolean imm_op, return 0; } -static bfd_boolean check_for_nop = FALSE; +#define NOP_CHECK_INTERRUPT (1 << 0) +#define NOP_CHECK_CPU12 (1 << 1) +#define NOP_CHECK_CPU19 (1 << 2) + +static signed int check_for_nop = 0; #define is_opcode(NAME) (strcmp (opcode->name, NAME) == 0) @@ -2380,7 +2462,6 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) const char * error_message; static signed int repeat_count = 0; bfd_boolean fix_emitted; - bfd_boolean nop_check_needed = FALSE; /* Opcode is the one from opcodes table line contains something like @@ -2513,20 +2594,20 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) repeat_count = 0; } - if (check_for_nop && is_opcode ("nop")) - check_for_nop = FALSE; - - switch (fmt) + if (check_for_nop) { - case 0: /* Emulated. */ - switch (opcode->insn_opnumb) + if (! is_opcode ("nop")) { - case 0: - if (is_opcode ("eint") || is_opcode ("dint")) + bfd_boolean doit = FALSE; + + do { - if (check_for_nop) + switch (check_for_nop & - check_for_nop) { - if (warn_interrupt_nops) + case NOP_CHECK_INTERRUPT: + if (warn_interrupt_nops + || silicon_errata_warn & SILICON_ERRATA_CPU42 + || silicon_errata_warn & SILICON_ERRATA_CPU42_PLUS) { if (gen_interrupt_nops) as_warn (_("NOP inserted between two instructions that change interrupt state")); @@ -2534,18 +2615,56 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) as_warn (_("a NOP might be needed here because of successive changes in interrupt state")); } - if (gen_interrupt_nops) - { - /* Emit a NOP between interrupt enable/disable. - See 1.3.4.1 of the MSP430x5xx User Guide. */ - insn_length += 2; - frag = frag_more (2); - bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag); - } - } + if (gen_interrupt_nops + || silicon_errata_fix & SILICON_ERRATA_CPU42_PLUS) + /* Emit a NOP between interrupt enable/disable. + See 1.3.4.1 of the MSP430x5xx User Guide. */ + doit = TRUE; + break; + + case NOP_CHECK_CPU12: + if (silicon_errata_warn & SILICON_ERRATA_CPU12) + as_warn (_("CPU12: CMP/BIT with PC destinstion ignores next instruction")); + + if (silicon_errata_fix & SILICON_ERRATA_CPU12) + doit = TRUE; + break; + + case NOP_CHECK_CPU19: + if (silicon_errata_warn & SILICON_ERRATA_CPU19) + as_warn (_("CPU19: Instruction setting CPUOFF must be followed by a NOP")); - nop_check_needed = TRUE; + if (silicon_errata_fix & SILICON_ERRATA_CPU19) + doit = TRUE; + break; + + default: + as_bad (_("internal error: unknown nop check state")); + break; + } + 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; + } + + switch (fmt) + { + case 0: /* Emulated. */ + switch (opcode->insn_opnumb) + { + case 0: + if (is_opcode ("eint") || is_opcode ("dint")) + check_for_nop |= NOP_CHECK_INTERRUPT; /* Set/clear bits instructions. */ if (extended_op) @@ -2574,30 +2693,37 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) bin |= (op1.reg | (op1.am << 7)); - if (is_opcode ("clr") && bin == 0x4302 /* CLR R2*/) + /* If the PC is the destination... */ + if (op1.am == 0 && op1.reg == 0 + /* ... and the opcode alters the SR. */ + && !(is_opcode ("bic") || is_opcode ("bis") || is_opcode ("mov") + || is_opcode ("bicx") || is_opcode ("bisx") || is_opcode ("movx"))) { - if (check_for_nop) - { - if (warn_interrupt_nops) - { - if (gen_interrupt_nops) - as_warn (_("NOP inserted between two instructions that change interrupt state")); - else - as_warn (_("a NOP might be needed here because of successive changes in interrupt state")); - } - - if (gen_interrupt_nops) - { - /* Emit a NOP between interrupt enable/disable. - See 1.3.4.1 of the MSP430x5xx User Guide. */ - insn_length += 2; - frag = frag_more (2); - bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag); - } - } - - nop_check_needed = TRUE; + if (silicon_errata_fix & SILICON_ERRATA_CPU11) + as_bad (_("CPU11: PC is destinstion of SR altering instruction")); + else if (silicon_errata_warn & SILICON_ERRATA_CPU11) + as_warn (_("CPU11: PC is destinstion of SR altering instruction")); } + + /* If the status register is the destination... */ + if (op1.am == 0 && op1.reg == 2 + /* ... and the opcode alters the SR. */ + && (is_opcode ("adc") || is_opcode ("dec") || is_opcode ("decd") + || is_opcode ("inc") || is_opcode ("incd") || is_opcode ("inv") + || is_opcode ("sbc") || is_opcode ("sxt") + || is_opcode ("adcx") || is_opcode ("decx") || is_opcode ("decdx") + || is_opcode ("incx") || is_opcode ("incdx") || is_opcode ("invx") + || is_opcode ("sbcx") + )) + { + if (silicon_errata_fix & SILICON_ERRATA_CPU13) + as_bad (_("CPU13: SR is destinstion of SR altering instruction")); + else if (silicon_errata_warn & SILICON_ERRATA_CPU13) + as_warn (_("CPU13: SR is destinstion 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); @@ -2691,6 +2817,19 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) break; } + /* If the status register is the destination... */ + if (op1.am == 0 && op1.reg == 2 + /* ... and the opcode alters the SR. */ + && (is_opcode ("rla") || is_opcode ("rlc") + || is_opcode ("rlax") || is_opcode ("rlcx") + )) + { + if (silicon_errata_fix & SILICON_ERRATA_CPU13) + as_bad (_("CPU13: SR is destinstion of SR altering instruction")); + else if (silicon_errata_warn & SILICON_ERRATA_CPU13) + as_warn (_("CPU13: SR is destinstion of SR altering instruction")); + } + if (extended_op) { if (!addr_op) @@ -3297,33 +3436,56 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7)); + /* If the PC is the destination... */ + if (op2.am == 0 && op2.reg == 0 + /* ... and the opcode alters the SR. */ + && !(is_opcode ("bic") || is_opcode ("bis") || is_opcode ("mov") + || is_opcode ("bicx") || is_opcode ("bisx") || is_opcode ("movx"))) + { + if (silicon_errata_fix & SILICON_ERRATA_CPU11) + as_bad (_("CPU11: PC is destinstion of SR altering instruction")); + else if (silicon_errata_warn & SILICON_ERRATA_CPU11) + as_warn (_("CPU11: PC is destinstion of SR altering instruction")); + } + + /* If the status register is the destination... */ + if (op2.am == 0 && op2.reg == 2 + /* ... and the opcode alters the SR. */ + && (is_opcode ("add") || is_opcode ("addc") || is_opcode ("and") + || is_opcode ("dadd") || is_opcode ("sub") || is_opcode ("subc") + || is_opcode ("xor") + || is_opcode ("addx") || is_opcode ("addcx") || is_opcode ("andx") + || is_opcode ("daddx") || is_opcode ("subx") || is_opcode ("subcx") + || is_opcode ("xorx") + )) + { + if (silicon_errata_fix & SILICON_ERRATA_CPU13) + as_bad (_("CPU13: SR is destinstion of SR altering instruction")); + else if (silicon_errata_warn & SILICON_ERRATA_CPU13) + as_warn (_("CPU13: SR is destinstion 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)) { - if (check_for_nop) - { - if (warn_interrupt_nops) - { - if (gen_interrupt_nops) - as_warn (_("NOP inserted between two instructions that change interrupt state")); - else - as_warn (_("a NOP might be needed here because of successive changes in interrupt state")); - } - - if (gen_interrupt_nops) - { - /* Emit a NOP between interrupt enable/disable. - See 1.3.4.1 of the MSP430x5xx User Guide. */ - insn_length += 2; - frag = frag_more (2); - bfd_putl16 ((bfd_vma) 0x4303 /* NOP */, frag); - } - } - - nop_check_needed = TRUE; + /* 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; } + if (((is_opcode ("bis") && bin == 0xd032) + || (is_opcode ("mov") && bin == 0x4032) + || (is_opcode ("xor") && bin == 0xe032)) + && op1.mode == OP_EXP + && op1.exp.X_op == O_constant + && (op1.exp.X_add_number & 0x10) == 0x10) + check_for_nop |= NOP_CHECK_CPU19; + /* Compute the entire length of the instruction in bytes. */ op_length = (extended_op ? 2 : 0) /* The extension word. */ + 2 /* The opcode */ @@ -3433,6 +3595,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) } dwarf2_emit_insn (insn_length); + + /* If the PC is the destination... */ + if (op2.am == 0 && op2.reg == 0 + /* ... but the opcode does not alter the destination. */ + && (is_opcode ("cmp") || is_opcode ("bit") || is_opcode ("cmpx"))) + check_for_nop |= NOP_CHECK_CPU12; break; case 2: /* Single-operand mostly instr. */ @@ -3464,6 +3632,17 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) break; } + /* If the status register is the destination... */ + if (op1.am == 0 && op1.reg == 2 + /* ... and the opcode alters the SR. */ + && (is_opcode ("rra") || is_opcode ("rrc") || is_opcode ("sxt"))) + { + if (silicon_errata_fix & SILICON_ERRATA_CPU13) + as_bad (_("CPU13: SR is destinstion of SR altering instruction")); + else if (silicon_errata_warn & SILICON_ERRATA_CPU13) + as_warn (_("CPU13: SR is destinstion of SR altering instruction")); + } + insn_length = (extended_op ? 2 : 0) + 2 + (op1.ol * 2); frag = frag_more (insn_length); where = frag - frag_now->fr_literal; @@ -3726,7 +3905,6 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line) } input_line_pointer = line; - check_for_nop = nop_check_needed; return 0; } @@ -4461,8 +4639,8 @@ msp430_fix_adjustable (struct fix *fixp ATTRIBUTE_UNUSED) void msp430_md_end (void) { - if (check_for_nop == TRUE && warn_interrupt_nops) - as_warn ("assembly finished with the last instruction changing interrupt state - a NOP might be needed"); + if (check_for_nop) + as_warn ("assembly finished without a possibly needed NOP instruction"); bfd_elf_add_proc_attr_int (stdoutput, OFBA_MSPABI_Tag_ISA, target_is_430x () ? 2 : 1); diff --git a/gas/doc/c-msp430.texi b/gas/doc/c-msp430.texi index 2a372dbecef..5b72c769892 100644 --- a/gas/doc/c-msp430.texi +++ b/gas/doc/c-msp430.texi @@ -36,6 +36,40 @@ also enables NOP generation unless the @option{-mN} is also specified. selects the cpu architecture. If the architecture is 430Xv2 then this also enables NOP generation unless the @option{-mN} is also specified. +@item -msilicon-errata=@var{name}[,@var{name}@dots{}] +Implements a fixup for named silicon errata. Multiple silicon errata +can be specified by multiple uses of the @option{-msilicon-errata} +option and/or by including the errata names, separated by commas, on +an individual @option{-msilicon-errata} option. Errata names +currently recognised by the assembler are: + +@table @code +@item cpu4 +@code{PUSH #4} and @option{PUSH #8} need longer encodings on the +MSP430. This option is enabled by default, and cannot be disabled. +@item cpu8 +Do not set the @code{SP} to an odd value. +@item cpu11 +Do not update the @code{SR} and the @code{PC} in the same instruction. +@item cpu12 +Do not use the @code{PC} in a @code{CMP} or @code{BIT} instruction. +@item cpu13 +Do not use an arithmetic instruction to modify the @code{SR}. +@item cpu19 +Insert @code{NOP} after @code{CPUOFF}. +@item cpu42 +Warn where a @code{NOP} ought to be present after enabling interrupts. +@item cpu42+ +Add @code{NOP} after enabling interrupts. +@end table + +@item -msilicon-errata-warn=@var{name}[,@var{name}@dots{}] +Like the @option{-msilicon-errata} option except that instead of +fixing the specified errata, a warning message is issued instead. +This option can be used alongside @option{-msilicon-errata} to +generate messages whenever a problem is fixed, or on its own in order +to inspect code for potential problems. + @item -mP enables polymorph instructions handler. diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 07ec4c8a280..89d282f9268 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2015-10-22 Nick Clifton + + * gas/msp430/errata_fixes.s: New test source file. + * gas/msp430/errata_fixes.d: New test control file. + * gas/msp430/errata_warns.s: New test source file. + * gas/msp430/errata_warns.d: New test control file. + * gas/msp430/errata_warns.l: New test message file. + * gas/msp430/msp430.exp: Run the new tests. + * gas/msp430/bad.l: Update expected warning messages + * gas/msp430/msp430.exp: Run the new tests. + 2015-10-22 H.J. Lu * gas/i386/i386.exp: Run x86-64-gotpcrel. diff --git a/gas/testsuite/gas/msp430/bad.l b/gas/testsuite/gas/msp430/bad.l index 8de13389993..6cc3e3a299d 100644 --- a/gas/testsuite/gas/msp430/bad.l +++ b/gas/testsuite/gas/msp430/bad.l @@ -7,8 +7,9 @@ [^:]*: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 [^:]*: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 -[^:]*: Warning: assembly finished with the last instruction changing interrupt state - a NOP might be needed +[^:]*: Warning: assembly finished without a possibly needed NOP instruction diff --git a/gas/testsuite/gas/msp430/errata_fixes.d b/gas/testsuite/gas/msp430/errata_fixes.d new file mode 100644 index 00000000000..c1164055bda --- /dev/null +++ b/gas/testsuite/gas/msp430/errata_fixes.d @@ -0,0 +1,23 @@ +#name: Fixes for Silicon Errata +#source: errata_fixes.s +#as: -msilicon-errata=cpu4,cpu12,cpu19 +#objdump: -d --prefix-addresses --show-raw-insn + +.*: +file format .*msp.* + +Disassembly of section .text: +0+0000 <[^>]*> 30 12 04 00[ ]+push #4 ; +0+0004 <[^>]*> 30 12 08 00[ ]+push #8 ; +0+0008 <[^>]*> 10 c3[ ]+bic #1, r0 ;r3 As==01$ +0+000a <[^>]*> 10 d3[ ]+bis #1, r0 ;r3 As==01$ +0+000c <[^>]*> 10 43[ ]+br #1 ;r3 As==01$ +0+000e <[^>]*> 10 92 c8 00[ ]+cmp &0x00c8,r0 ;0x00c8 +0+0012 <[^>]*> 03 43[ ]+nop +0+0014 <[^>]*> 00 b1[ ]+bit r1, r0 ; +0+0016 <[^>]*> 03 43[ ]+nop +0+0018 <[^>]*> 32 d0 10 00[ ]+bis #16, r2 ;#0x0010 +0+001c <[^>]*> 03 43[ ]+nop +0+001e <[^>]*> 32 40 10 00[ ]+mov #16, r2 ;#0x0010 +0+0022 <[^>]*> 03 43[ ]+nop +0+0024 <[^>]*> 32 e0 10 00[ ]+xor #16, r2 ;#0x0010 +0+0028 <[^>]*> 03 43[ ]+nop diff --git a/gas/testsuite/gas/msp430/errata_fixes.s b/gas/testsuite/gas/msp430/errata_fixes.s new file mode 100644 index 00000000000..dd6d14d1e2b --- /dev/null +++ b/gas/testsuite/gas/msp430/errata_fixes.s @@ -0,0 +1,24 @@ + .text +errata: + .cpu msp430 + # CPU4: PUSH #4/#8 has to be encoded using the long form + push #4 + push #8 + + # CPU11: The SR flags can be left in a bogus state after writing to the PC + # Instructions that do not set the SR flags are unaffected. + bic #1, pc + bis #1, pc + mov #1, pc + + #CPU12: A CMP or BIT instruction with the PC as the second operand may + # not execute the instruction after it - so a NOP must be inserted. + cmp &200, PC + bit r1, pc + + #CPU19: Instructions that sets CPUOFF must be followed by a NOP + bis #0x10, r2 + mov #0x10, r2 + xor #0x10, r2 + nop + \ No newline at end of file diff --git a/gas/testsuite/gas/msp430/errata_warns.d b/gas/testsuite/gas/msp430/errata_warns.d new file mode 100644 index 00000000000..eef8c2e22f5 --- /dev/null +++ b/gas/testsuite/gas/msp430/errata_warns.d @@ -0,0 +1,4 @@ +#name: Warning Messages for Silicon Errata +#source: errata_warns.s +#as: -msilicon-errata-warn=cpu4,cpu8,cpu11,cpu12,cpu13,cpu19 +#error-output: errata_warns.l diff --git a/gas/testsuite/gas/msp430/errata_warns.l b/gas/testsuite/gas/msp430/errata_warns.l new file mode 100644 index 00000000000..52df6b95e31 --- /dev/null +++ b/gas/testsuite/gas/msp430/errata_warns.l @@ -0,0 +1,44 @@ +[^:]*: Assembler messages: +[^:]*:5: Warning: cpu4: not converting PUSH #4 to shorter form +[^:]*:6: Warning: cpu4: not converting PUSH #8 to shorter form +[^:]*:11: Warning: CPU8: Stack pointer accessed with an odd offset +[^:]*:12: Warning: CPU8: Stack pointer accessed with an odd offset +[^:]*:13: Warning: CPU8: Stack pointer accessed with an odd offset +[^:]*:14: Warning: CPU8: Stack pointer accessed with an odd offset +[^:]*:15: Warning: CPU8: Stack pointer accessed with an odd offset +[^:]*:18: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:19: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:20: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:21: Warning: CPU12: CMP/BIT with PC destinstion ignores next instruction +[^:]*:21: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:22: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:23: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:24: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:25: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:26: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:30: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:31: Warning: CPU12: CMP/BIT with PC destinstion ignores next instruction +[^:]*:31: Warning: CPU11: PC is destinstion of SR altering instruction +[^:]*:34: Warning: CPU12: CMP/BIT with PC destinstion ignores next instruction +[^:]*:34: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:35: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:36: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:37: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:38: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:39: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:40: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:41: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:42: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:43: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:44: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:45: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:46: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:47: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:48: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:49: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:50: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:51: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:52: Warning: CPU13: SR is destinstion of SR altering instruction +[^:]*:56: Warning: CPU19: Instruction setting CPUOFF must be followed by a NOP +[^:]*:57: Warning: CPU19: Instruction setting CPUOFF must be followed by a NOP +[^:]*:57: Warning: CPU13: SR is destinstion of SR altering instruction diff --git a/gas/testsuite/gas/msp430/errata_warns.s b/gas/testsuite/gas/msp430/errata_warns.s new file mode 100644 index 00000000000..c67d9c73698 --- /dev/null +++ b/gas/testsuite/gas/msp430/errata_warns.s @@ -0,0 +1,59 @@ + .text +errata: + .cpu msp430 + # CPU4: PUSH #4/#8 has to be encoded using the long form + push #4 + push #8 + + # CPU8: Do not use odd offsets with the stack pointer + .set fred,3 + .set bert,1 + mov.w #4, 7(sp) + mov 3(r1), 5(r0) + mov.b @r10+,fred-bert+1(sp) + add.w #1,1(sp) + add.w #7,-1(sp) + + # CPU11: The SR flags can be left in a bogus state after writing to the PC + add.w #3, pc + and #1, pc + bit #1, pc + dadd #1, pc + inc pc + incd pc + sub #1, pc + subc #1, pc + xor #1, pc + + #CPU12: A CMP or BIT instruction with the PC as the second operand may + # not execute the instruction after it. + cmp &200, PC + bit r1, pc + + #CPU13: Arithmetic operations with SR as the destination do not work. + add #3, sr + adc sr + addc #3, sr + and #3, sr + dadd #3, sr + dec sr + decd sr + inc sr + incd sr + inv sr + rla sr + rlc sr + rra sr + rrc sr + sbc sr + sub #3, sr + subc #3, sr + sxt sr + xor #3, sr + + #CPU19: Instructions that sets CPUOFF must be followed by a NOP + bis #0x10, r2 + mov #0x10, r2 + xor #0x10, r2 + nop + \ No newline at end of file diff --git a/gas/testsuite/gas/msp430/msp430.exp b/gas/testsuite/gas/msp430/msp430.exp index 78aa7641729..7742f554ed3 100644 --- a/gas/testsuite/gas/msp430/msp430.exp +++ b/gas/testsuite/gas/msp430/msp430.exp @@ -22,4 +22,6 @@ if [expr [istarget "msp430-*-*"]] then { run_dump_test "opcode" run_dump_test "msp430x" run_dump_test "bad" + run_dump_test "errata_warns" + run_dump_test "errata_fixes" } -- 2.30.2