/* Configurable Xtensa ISA support.
- Copyright 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "xtensa-isa.h"
#include "xtensa-isa-internal.h"
} \
} while (0)
+
\f
/* Instruction buffers. */
both. */
int
-xtensa_insnbuf_to_chars (xtensa_isa isa, const xtensa_insnbuf insn, char *cp,
+xtensa_insnbuf_to_chars (xtensa_isa isa,
+ const xtensa_insnbuf insn,
+ unsigned char *cp,
int num_chars)
{
xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
/* Inward conversion from byte stream to xtensa_insnbuf. See
xtensa_insnbuf_to_chars for a discussion of why this is complicated
by endianness. */
-
+
void
-xtensa_insnbuf_from_chars (xtensa_isa isa, xtensa_insnbuf insn, const char *cp,
+xtensa_insnbuf_from_chars (xtensa_isa isa,
+ xtensa_insnbuf insn,
+ const unsigned char *cp,
int num_chars)
{
xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
int word_inx = byte_to_word_index (i);
int bit_inx = byte_to_bit_index (i);
- insn[word_inx] |= (*cp & 0xff) << bit_inx;
+ insn[word_inx] |= (unsigned) (*cp & 0xff) << bit_inx;
}
}
xtensa_sysreg_internal *sreg = &isa->sysregs[n];
is_user = sreg->is_user;
- isa->sysreg_table[is_user][sreg->number] = n;
+ if (sreg->number >= 0)
+ isa->sysreg_table[is_user][sreg->number] = n;
}
/* Set up the interface lookup table. */
- isa->interface_lookup_table =
+ isa->interface_lookup_table =
bfd_malloc (isa->num_interfaces * sizeof (xtensa_lookup_entry));
CHECK_ALLOC_FOR_INIT (isa->interface_lookup_table, NULL, errno_p,
error_msg_p);
sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
/* Set up the funcUnit lookup table. */
- isa->funcUnit_lookup_table =
+ isa->funcUnit_lookup_table =
bfd_malloc (isa->num_funcUnits * sizeof (xtensa_lookup_entry));
CHECK_ALLOC_FOR_INIT (isa->funcUnit_lookup_table, NULL, errno_p,
error_msg_p);
the memory allocated by xtensa_isa_init and restore the xtensa_isa
structure to its initial state. */
- if (intisa->opname_lookup_table)
- {
- free (intisa->opname_lookup_table);
- intisa->opname_lookup_table = 0;
- }
+ free (intisa->opname_lookup_table);
+ intisa->opname_lookup_table = 0;
- if (intisa->state_lookup_table)
- {
- free (intisa->state_lookup_table);
- intisa->state_lookup_table = 0;
- }
+ free (intisa->state_lookup_table);
+ intisa->state_lookup_table = 0;
+
+ free (intisa->sysreg_lookup_table);
+ intisa->sysreg_lookup_table = 0;
- if (intisa->sysreg_lookup_table)
- {
- free (intisa->sysreg_lookup_table);
- intisa->sysreg_lookup_table = 0;
- }
for (n = 0; n < 2; n++)
{
- if (intisa->sysreg_table[n])
- {
- free (intisa->sysreg_table[n]);
- intisa->sysreg_table[n] = 0;
- }
+ free (intisa->sysreg_table[n]);
+ intisa->sysreg_table[n] = 0;
}
- if (intisa->interface_lookup_table)
- {
- free (intisa->interface_lookup_table);
- intisa->interface_lookup_table = 0;
- }
+ free (intisa->interface_lookup_table);
+ intisa->interface_lookup_table = 0;
- if (intisa->funcUnit_lookup_table)
- {
- free (intisa->funcUnit_lookup_table);
- intisa->funcUnit_lookup_table = 0;
- }
+ free (intisa->funcUnit_lookup_table);
+ intisa->funcUnit_lookup_table = 0;
}
int
-xtensa_isa_length_from_chars (xtensa_isa isa, const char *cp)
+xtensa_isa_length_from_chars (xtensa_isa isa, const unsigned char *cp)
{
xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
return (intisa->length_decode_fn) (cp);
int
-xtensa_isa_num_pipe_stages (xtensa_isa isa)
+xtensa_isa_num_pipe_stages (xtensa_isa isa)
{
- int num_opcodes, num_uses;
xtensa_opcode opcode;
xtensa_funcUnit_use *use;
- int i, stage, max_stage = XTENSA_UNDEFINED;
+ int num_opcodes, num_uses;
+ int i, stage;
+ static int max_stage = XTENSA_UNDEFINED;
+
+ /* Only compute the value once. */
+ if (max_stage != XTENSA_UNDEFINED)
+ return max_stage + 1;
num_opcodes = xtensa_isa_num_opcodes (isa);
for (opcode = 0; opcode < num_opcodes; opcode++)
if (strcasecmp (fmtname, intisa->formats[fmt].name) == 0)
return fmt;
}
-
+
xtisa_errno = xtensa_isa_bad_format;
sprintf (xtisa_error_msg, "format \"%s\" not recognized", fmtname);
return XTENSA_UNDEFINED;
xtensa_opcode_lookup (xtensa_isa isa, const char *opname)
{
xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
- xtensa_lookup_entry entry, *result;
+ xtensa_lookup_entry entry, *result = 0;
if (!opname || !*opname)
{
return XTENSA_UNDEFINED;
}
- entry.key = opname;
- result = bsearch (&entry, intisa->opname_lookup_table, intisa->num_opcodes,
- sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+ if (intisa->num_opcodes != 0)
+ {
+ entry.key = opname;
+ result = bsearch (&entry, intisa->opname_lookup_table,
+ intisa->num_opcodes, sizeof (xtensa_lookup_entry),
+ xtensa_isa_name_compare);
+ }
if (!result)
{
slot_id = intisa->formats[fmt].slot_id[slot];
opc = (intisa->slots[slot_id].opcode_decode_fn) (slotbuf);
- if (opc == XTENSA_UNDEFINED)
- {
- xtisa_errno = xtensa_isa_bad_opcode;
- strcpy (xtisa_error_msg, "cannot decode opcode");
- }
- return opc;
+ if (opc != XTENSA_UNDEFINED)
+ return opc;
+
+ xtisa_errno = xtensa_isa_bad_opcode;
+ strcpy (xtisa_error_msg, "cannot decode opcode");
+ return XTENSA_UNDEFINED;
}
uint32 test_val, orig_val;
intop = get_operand (intisa, opc, opnd);
- if (!intop) return -1;
+ if (!intop)
+ return -1;
if (!intop->encode)
{
/* This is a default operand for a field. How can we tell if the
value fits in the field? Write the value into the field,
read it back, and then make sure we get the same value. */
-
- xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
static xtensa_insnbuf tmpbuf = 0;
int slot_id;
was successfully encoded is to decode it and check if it matches
the original value. */
orig_val = *valp;
- if ((*intop->encode) (valp) ||
- (test_val = *valp, (*intop->decode) (&test_val)) ||
- test_val != orig_val)
+ if ((*intop->encode) (valp)
+ || (test_val = *valp, (*intop->decode) (&test_val))
+ || test_val != orig_val)
{
xtisa_errno = xtensa_isa_bad_value;
sprintf (xtisa_error_msg, "cannot encode operand value 0x%08x", *valp);
return iclass->stateOperands[stOp].inout;
}
+
\f
/* Interface Operands. */
/* The expected number of regfiles is small; use a linear search. */
for (n = 0; n < intisa->num_regfiles; n++)
{
- if (!strcmp (intisa->regfiles[n].name, name))
+ if (!filename_cmp (intisa->regfiles[n].name, name))
return n;
}
as their parents. */
if (intisa->regfiles[n].parent != n)
continue;
- if (!strcmp (intisa->regfiles[n].shortname, shortname))
+ if (!filename_cmp (intisa->regfiles[n].shortname, shortname))
return n;
}
return intisa->regfiles[rf].num_entries;
}
+
\f
/* Processor States. */
xtensa_state_lookup (xtensa_isa isa, const char *name)
{
xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
- xtensa_lookup_entry entry, *result;
+ xtensa_lookup_entry entry, *result = 0;
if (!name || !*name)
{
return XTENSA_UNDEFINED;
}
- entry.key = name;
- result = bsearch (&entry, intisa->state_lookup_table, intisa->num_states,
- sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+ if (intisa->num_states != 0)
+ {
+ entry.key = name;
+ result = bsearch (&entry, intisa->state_lookup_table, intisa->num_states,
+ sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+ }
if (!result)
{
return 0;
}
+
+int
+xtensa_state_is_shared_or (xtensa_isa isa, xtensa_state st)
+{
+ xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+ CHECK_STATE (intisa, st, XTENSA_UNDEFINED);
+ if ((intisa->states[st].flags & XTENSA_STATE_IS_SHARED_OR) != 0)
+ return 1;
+ return 0;
+}
+
+
\f
/* Sysregs. */
xtensa_sysreg_lookup_name (xtensa_isa isa, const char *name)
{
xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
- xtensa_lookup_entry entry, *result;
+ xtensa_lookup_entry entry, *result = 0;
if (!name || !*name)
{
return XTENSA_UNDEFINED;
}
- entry.key = name;
- result = bsearch (&entry, intisa->sysreg_lookup_table, intisa->num_sysregs,
- sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+ if (intisa->num_sysregs != 0)
+ {
+ entry.key = name;
+ result = bsearch (&entry, intisa->sysreg_lookup_table,
+ intisa->num_sysregs, sizeof (xtensa_lookup_entry),
+ xtensa_isa_name_compare);
+ }
if (!result)
{
return 0;
}
+
\f
/* Interfaces. */
xtensa_interface_lookup (xtensa_isa isa, const char *ifname)
{
xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
- xtensa_lookup_entry entry, *result;
+ xtensa_lookup_entry entry, *result = 0;
if (!ifname || !*ifname)
{
return XTENSA_UNDEFINED;
}
- entry.key = ifname;
- result = bsearch (&entry, intisa->interface_lookup_table,
- intisa->num_interfaces,
- sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+ if (intisa->num_interfaces != 0)
+ {
+ entry.key = ifname;
+ result = bsearch (&entry, intisa->interface_lookup_table,
+ intisa->num_interfaces, sizeof (xtensa_lookup_entry),
+ xtensa_isa_name_compare);
+ }
if (!result)
{
return 0;
}
+
+int
+xtensa_interface_class_id (xtensa_isa isa, xtensa_interface intf)
+{
+ xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+ CHECK_INTERFACE (intisa, intf, XTENSA_UNDEFINED);
+ return intisa->interfaces[intf].class_id;
+}
+
+
\f
/* Functional Units. */
xtensa_funcUnit_lookup (xtensa_isa isa, const char *fname)
{
xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
- xtensa_lookup_entry entry, *result;
+ xtensa_lookup_entry entry, *result = 0;
if (!fname || !*fname)
{
return XTENSA_UNDEFINED;
}
- entry.key = fname;
- result = bsearch (&entry, intisa->funcUnit_lookup_table,
- intisa->num_funcUnits,
- sizeof (xtensa_lookup_entry), xtensa_isa_name_compare);
+ if (intisa->num_funcUnits != 0)
+ {
+ entry.key = fname;
+ result = bsearch (&entry, intisa->funcUnit_lookup_table,
+ intisa->num_funcUnits, sizeof (xtensa_lookup_entry),
+ xtensa_isa_name_compare);
+ }
if (!result)
{