/* tc-xtensa.c -- Assemble Xtensa instructions.
- Copyright (C) 2003-2019 Free Software Foundation, Inc.
+ Copyright (C) 2003-2021 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#include "elf/xtensa.h"
/* Provide default values for new configuration settings. */
-#ifndef XSHAL_ABI
-#define XSHAL_ABI 0
+#ifndef XTHAL_ABI_WINDOWED
+#define XTHAL_ABI_WINDOWED 0
+#endif
+
+#ifndef XTHAL_ABI_CALL0
+#define XTHAL_ABI_CALL0 1
+#endif
+
+#ifndef XTENSA_MARCH_EARLIEST
+#define XTENSA_MARCH_EARLIEST 0
#endif
#ifndef uint32
bfd_boolean density_supported;
bfd_boolean absolute_literals_supported;
+static unsigned microarch_earliest;
+
static vliw_insn cur_vinsn;
unsigned xtensa_num_pipe_stages;
This option is defined in BDF library. */
extern bfd_boolean elf32xtensa_separate_props;
+/* Xtensa ABI.
+ This option is defined in BDF library. */
+extern int elf32xtensa_abi;
+
static void
xtensa_setup_hw_workarounds (int earliest, int latest)
{
option_separate_props,
option_no_separate_props,
+
+ option_abi_windowed,
+ option_abi_call0,
};
const char *md_shortopts = "";
{ "separate-prop-tables", no_argument, NULL, option_separate_props },
+ { "abi-windowed", no_argument, NULL, option_abi_windowed },
+ { "abi-call0", no_argument, NULL, option_abi_call0 },
+
{ NULL, no_argument, NULL, 0 }
};
elf32xtensa_separate_props = FALSE;
return 1;
+ case option_abi_windowed:
+ elf32xtensa_abi = XTHAL_ABI_WINDOWED;
+ return 1;
+
+ case option_abi_call0:
+ elf32xtensa_abi = XTHAL_ABI_CALL0;
+ return 1;
+
default:
return 0;
}
}
}
-fini:
+ fini:
if (saw_comma || saw_colon)
goto err;
input_line_pointer = old_input_line_pointer;
return num_args;
-err:
+ err:
if (saw_comma)
as_bad (_("extra comma"));
else if (saw_colon)
return 0;
}
+ /* Without an operand, this is given a default immediate operand of 0. */
+ if ((strcmp (opname, "simcall") == 0 && microarch_earliest >= 280000))
+ {
+ if (*pnum_args == 0)
+ {
+ arg_strings[0] = (char *) xmalloc (2);
+ strcpy (arg_strings[0], "0");
+ *pnum_args = 1;
+ }
+ return 0;
+ }
+
if (strcmp (opname, "bbsi.l") == 0)
{
if (xg_check_num_args (pnum_args, 3, opname, arg_strings))
symbol will be in the output file. */
if (get_is_linkonce_section (stdoutput, sec))
{
- symbolP = symbol_new (name, sec, 0, frag);
+ symbolP = symbol_new (name, sec, frag, 0);
S_CLEAR_EXTERNAL (symbolP);
/* symbolP->local = 1; */
}
else
- symbolP = symbol_new (name, sec, 0, frag);
+ symbolP = symbol_new (name, sec, frag, 0);
xtensa_add_literal_sym (symbolP);
directive_state[directive_density] = XCHAL_HAVE_DENSITY;
directive_state[directive_absolute_literals] = XSHAL_USE_ABSOLUTE_LITERALS;
+
+ microarch_earliest = XTENSA_MARCH_EARLIEST;
}
void
case BFD_RELOC_8:
if (fixP->fx_subsy)
{
+ bfd_boolean neg = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
+ < S_GET_VALUE (fixP->fx_subsy);
+
switch (fixP->fx_r_type)
{
case BFD_RELOC_8:
- fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF8;
+ fixP->fx_r_type = neg
+ ? BFD_RELOC_XTENSA_NDIFF8 : BFD_RELOC_XTENSA_PDIFF8;
fixP->fx_signed = 0;
break;
case BFD_RELOC_16:
- fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF16;
+ fixP->fx_r_type = neg
+ ? BFD_RELOC_XTENSA_NDIFF16 : BFD_RELOC_XTENSA_PDIFF16;
fixP->fx_signed = 0;
break;
case BFD_RELOC_32:
- fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF32;
+ fixP->fx_r_type = neg
+ ? BFD_RELOC_XTENSA_NDIFF32 : BFD_RELOC_XTENSA_PDIFF32;
fixP->fx_signed = 0;
break;
default:
const struct trampoline_chain_entry *pa = a;
const struct trampoline_chain_entry *pb = b;
- if (pa->sym == pb->sym ||
- S_GET_VALUE (pa->sym) == S_GET_VALUE (pb->sym))
- if (pa->offset == pb->offset)
- return 0;
- else
- return pa->offset < pb->offset ? -1 : 1;
- else
- return S_GET_VALUE (pa->sym) < S_GET_VALUE (pb->sym) ? -1 : 1;
+ if (pa->sym != pb->sym)
+ {
+ valueT aval = S_GET_VALUE (pa->sym);
+ valueT bval = S_GET_VALUE (pb->sym);
+
+ if (aval != bval)
+ return aval < bval ? -1 : 1;
+ }
+ if (pa->offset != pb->offset)
+ return pa->offset < pb->offset ? -1 : 1;
+ return 0;
}
static void xg_sort_trampoline_chain (struct trampoline_chain *tc)
const struct trampoline_chain_entry *pb = &_pb->target;
symbolS *s1 = pa->sym;
symbolS *s2 = pb->sym;
- symbolS *tmp;
- tmp = symbol_symbolS (s1);
- if (tmp)
- s1 = tmp;
+ if (s1 != s2)
+ {
+ symbolS *tmp = symbol_symbolS (s1);
+ if (tmp)
+ s1 = tmp;
- tmp = symbol_symbolS (s2);
- if (tmp)
- s2 = tmp;
+ tmp = symbol_symbolS (s2);
+ if (tmp)
+ s2 = tmp;
- if (s1 == s2)
- if (pa->offset == pb->offset)
- return 0;
- else
- return pa->offset < pb->offset ? -1 : 1;
- else
- return s1 < s2 ? -1 : 1;
+ if (s1 != s2)
+ return s1 < s2 ? -1 : 1;
+ }
+
+ if (pa->offset != pb->offset)
+ return pa->offset < pb->offset ? -1 : 1;
+ return 0;
}
static struct trampoline_chain *
struct trampoline_chain_index *idx = &ts->chain_index;
struct trampoline_chain c;
+ if (idx->n_entries == 0)
+ return NULL;
+
if (idx->needs_sorting)
{
qsort (idx->entry, idx->n_entries, sizeof (*idx->entry),
printf(" %ld <%d:%d> (%d) [%d]: ",
lpf->addr, lpf->priority, lpf->original_priority,
lpf->fragP->fr_line, count);
- //dump_frag(lpf->fragP);
+ /* dump_frag(lpf->fragP); */
}
}
}
return FALSE;
}
-
#define XTINFO_NAME "Xtensa_Info"
#define XTINFO_NAMESZ 12
#define XTINFO_TYPE 1
data = XNEWVEC (char, 100);
sprintf (data, "USE_ABSOLUTE_LITERALS=%d\nABI=%d\n",
- XSHAL_USE_ABSOLUTE_LITERALS, XSHAL_ABI);
+ XSHAL_USE_ABSOLUTE_LITERALS, xtensa_abi_choice ());
sz = strlen (data) + 1;
/* Add enough null terminators to pad to a word boundary. */
char label[10 + 2 * sizeof(fp)];
sprintf (label, ".L0_TR_%p", fp);
- lsym = (symbolS *)local_symbol_make (label, now_seg, 0, fp);
+ lsym = (symbolS *) local_symbol_make (label, now_seg, fp, 0);
fp->fr_symbol = lsym;
if (fp->tc_frag_data.needs_jump_around)
{
target_offset += unreach->tc_frag_data.text_expansion[0];
}
gas_assert (gen_label == NULL);
- gen_label = symbol_new (FAKE_LABEL_NAME, now_seg,
+ gen_label = symbol_new (FAKE_LABEL_NAME, now_seg, fragP,
fr_opcode - fragP->fr_literal
- + target_offset, fragP);
+ + target_offset);
break;
case ITYPE_INSN:
/* Create a local symbol pointing to the
end of the pool. */
sprintf (label, ".L0_LT_%p", poolbeg);
- lsym = (symbolS *)local_symbol_make (label, lps->seg,
- 0, poolend);
+ lsym = (symbolS *) local_symbol_make (label, lps->seg, poolend, 0);
poolbeg->fr_symbol = lsym;
/* Rest is done in xtensa_relax_frag. */
}