/* tc-msp430.c -- Assembler code for the Texas Instruments MSP430
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2017 Free Software Foundation, Inc.
Contributed by Dmitry Diky <diwil@mail.ru>
This file is part of GAS, the GNU Assembler.
int msp430_enable_relax;
int msp430_enable_polys;
-/* Set linkrelax here to avoid fixups in most sections. */
-int linkrelax = 1;
-
/* GCC uses the some condition codes which we'll
implement as new polymorph instructions.
? BFD_RELOC_MSP430_16_BYTE : BFD_RELOC_MSP430_16))
/* Generate a 16-bit pc-relative relocation.
- For the 430X we generate a relocation without linkwer range checking.
+ For the 430X we generate a relocation without linker range checking.
For the 430 we generate a relocation without assembler range checking
if we are handling an immediate value or a byte-width instruction. */
#undef CHECK_RELOC_MSP430_PCREL
subseg = now_subseg;
/* Now go to .profiler section. */
- obj_elf_change_section (".profiler", SHT_PROGBITS, 0, 0, 0, 0, 0);
+ obj_elf_change_section (".profiler", SHT_PROGBITS, 0, 0, 0, 0, 0, 0);
/* Save flags. */
emit_expr (& exp, 2);
{
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;
static void
msp430_set_arch (int option)
{
- char *str = (char *) alloca (32); /* 32 for good measure. */
+ char str[32]; /* 32 for good measure. */
input_line_pointer = extract_word (input_line_pointer, str, 32);
/* This is a copy of the same data structure found in gcc/config/msp430/msp430.c
Keep these two structures in sync.
- The data in this structure has been extracted from the devices.csv file
- released by TI, updated as of March 2016. */
+ The data in this structure has been extracted from version 1.194 of the
+ devices.csv file released by TI in September 2016. */
struct msp430_mcu_data
{
{ "msp430fg6626",2,8 },
{ "msp430fr2032",2,0 },
{ "msp430fr2033",2,0 },
+ { "msp430fr2110",2,0 },
+ { "msp430fr2111",2,0 },
{ "msp430fr2310",2,0 },
{ "msp430fr2311",2,0 },
{ "msp430fr2433",2,8 },
{ "msp430fr5858",2,8 },
{ "msp430fr5859",2,8 },
{ "msp430fr5867",2,8 },
- { "msp430fr5862",2,8 },
- { "msp430fr5864",2,8 },
{ "msp430fr58671",2,8 },
{ "msp430fr5868",2,8 },
{ "msp430fr5869",2,8 },
{ "msp430fr5888",2,8 },
{ "msp430fr5889",2,8 },
{ "msp430fr58891",2,8 },
- { "msp430fr5892",2,8 },
- { "msp430fr5894",2,8 },
{ "msp430fr5922",2,8 },
{ "msp430fr59221",2,8 },
{ "msp430fr5947",2,8 },
{ "msp430fr59891",2,8 },
{ "msp430fr5992",2,8 },
{ "msp430fr5994",2,8 },
+ { "msp430fr59941",2,8 },
{ "msp430fr5xx_6xxgeneric",2,8 },
{ "msp430fr6820",2,8 },
{ "msp430fr6822",2,8 },
};
int
-md_parse_option (int c, char * arg)
+md_parse_option (int c, const char * arg)
{
switch (c)
{
msp430_section (int arg)
{
char * saved_ilp = input_line_pointer;
- char * name = obj_elf_section_name ();
+ const char * name = obj_elf_section_name ();
msp430_make_init_symbols (name);
return from;
}
-char *
+const char *
md_atof (int type, char * litP, int * sizeP)
{
return ieee_md_atof (type, litP, sizeP, FALSE);
bfd_set_arch_mach (stdoutput, TARGET_ARCH,
target_is_430x () ? bfd_mach_msp430x : bfd_mach_msp11);
+
+ /* Set linkrelax here to avoid fixups in most sections. */
+ linkrelax = 1;
}
/* Returns the register number equivalent to the string T.
else
{
as_bad (_
- ("unknown expression in operand %s. use #llo() #lhi() #hlo() #hhi() "),
+ ("unknown expression in operand %s. Use #llo(), #lhi(), #hlo() or #hhi()"),
l);
return 1;
}
if (op->am == 2)
{
- char *__tl = "0";
+ char *__tl = (char *) "0";
op->mode = OP_EXP;
op->am = 1;
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
instruction that does not support it. Look for an alternative extended
instruction that has the same name without the period. Eg: "add.a"
becomes "adda". Although this not an officially supported way of
- specifing instruction aliases other MSP430 assemblers allow it. So we
+ specifying instruction aliases other MSP430 assemblers allow it. So we
support it for compatibility purposes. */
if (addr_op && opcode->fmt >= 0)
{
- char * old_name = opcode->name;
+ const char * old_name = opcode->name;
char real_name[32];
sprintf (real_name, "%sa", old_name);
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. */
parse_exp (l1 + 1, &(op1.exp));
if (op1.exp.X_op != O_constant)
{
- as_bad (_("expected constant expression for first argument of %s"),
+ as_bad (_("expected constant expression as first argument of %s"),
opcode->name);
break;
}
parse_exp (l1 + 1, &(op1.exp));
if (op1.exp.X_op != O_constant)
{
- as_bad (_("expected constant expression for first argument of %s"),
+ as_bad (_("expected constant expression as first argument of %s"),
opcode->name);
break;
}
break;
default:
- as_bad (_("Illegal emulated instruction "));
+ as_bad (_("Illegal emulated instruction"));
break;
}
break;
if (x > 512 || x < -511)
{
- as_bad (_("Wrong displacement %d"), x << 1);
+ as_bad (_("Wrong displacement %d"), x << 1);
break;
}
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;
}
if (!cmd[0])
{
- as_bad (_("can't find opcode "));
+ as_bad (_("can't find opcode"));
return;
}
return fixp->fx_frag->fr_address + fixp->fx_where;
}
-/* Replaces standard TC_FORCE_RELOCATION_LOCAL.
+/* Addition to the standard TC_FORCE_RELOCATION_LOCAL.
Now it handles the situation when relocations
have to be passed to linker. */
int
&& !msp430_enable_relax)
return 1;
- return (!fixp->fx_pcrel
- || generic_force_reloc (fixp));
+ return 0;
}
static arelent * relocs[MAX_RELOC_EXPANSION + 1];
arelent *reloc;
- reloc = xmalloc (sizeof (arelent));
+ reloc = XNEW (arelent);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
because there can be multiple incarnations of the same label, with
exactly the same name, in any given section and the linker will have
no way to identify the correct one. Instead we just have to hope
- that no relaxtion will occur between the local label and the other
+ that no relaxation will occur between the local label and the other
symbol in the expression.
Similarly we have to compute differences between symbols in the .eh_frame
&& ! S_IS_GAS_LOCAL (fixp->fx_addsy)
&& ! S_IS_GAS_LOCAL (fixp->fx_subsy))
{
- arelent * reloc2 = xmalloc (sizeof * reloc);
+ arelent * reloc2 = XNEW (arelent);
relocs[0] = reloc2;
relocs[1] = reloc;
reloc2->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
else
{
- reloc2->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ reloc2->sym_ptr_ptr = XNEW (asymbol *);
*reloc2->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
}
}
else
{
- reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
}
return & no_relocs;
}
#endif
- reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->addend = fixp->fx_offset;
}
else if (fragP->fr_symbol)
{
- /* Its got a segment, but its not ours. Even if fr_symbol is in
+ /* It's got a segment, but it's not ours. Even if fr_symbol is in
an absolute segment, we don't know a displacement until we link
object files. So it will always be long. This also applies to
labels in a subsegment of current. Liker may relax it to short
break;
default:
- as_fatal (_("internal inconsistency problem in %s: %lx"),
+ as_fatal (_("internal inconsistency problem in %s: %lx"),
__FUNCTION__, (long) fragP->fr_subtype);
break;
}