This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 2/4] [ARC] Add support for address type syntax
Some NPS-400 instructions include an address type in an indirect
argument, which includes the name of the address type followed by
a colon, before the usual register or immediate argument. For
example, the syntax of one instruction using an address type is:
bdalc DST, [cm:SRC1], SRC1, SRC2
where the second argument is an offset into the CMEM area given by
SRC1.
In order to add support for address types, there are two main
changes:
1. Addition of the colon operand, which is handled in much the
same way as brackets are already handled.
2. Addition of support for address type operands. There are a
limited number of address types, which are all implemented in this
patch.
- In the assembler, address types are supported in a similar way to
how registers are supported: a token representing an address type
has its X_op field set to O_addrtype, and its X_add_number is an
enum value that represents a particular address type. These values
are added to include/opcode/arc.h in the arc_nps_address_type
enum. In order for X_op and X_add_number to be set correctly,
arc_parse_name is modified to parse address types as well as
registers, using the arc_addrtype_hash to map from address type
names to enum values.
- In the disassembler, colons and address types are printed out
when necessary, as determined by the operands of opcode that has
been matched.
- In libopcodes, the operands for colons and address types are
declared. The insert functions don't actually insert anything
because the address type for an operand is actually determined
by the combination of major opcode and subopcodes of an
instruction. However, they do check that the address type being
inserted matches the specified address type for the operand, in
order to reject opcodes that are invalid for a given address
type.
gas/ChangeLog:
* config/tc-arc.c: Add new global arc_addrtype_hash.
Define O_colon and O_addrtype.
(debug_exp): Add O_colon and O_addrtype.
(tokenize_arguments): Handle colon and address type
tokens.
(declare_addrtype): New function.
(md_begin): Initialise arc_addrtype_hash.
(arc_parse_name): Add lookup of address types.
(assemble_insn): Handle colons and address types by
ignoring them.
include/ChangeLog:
* opcode/arc.h: Add ARC_OPERAND_ADDRTYPE,
ARC_OPERAND_COLON. Add the arc_nps_address_type enum and
ARC_NUM_ADDRTYPES.
opcodes/ChangeLog:
* arc-dis.c: Add new globals addrtypenames,
addrtypenames_max, and addtypeunknown.
(get_addrtype): New function.
(print_insn_arc): Print colons and address types when
required.
* arc-opc.c: Add MAKE_INSERT_NPS_ADDRTYPE macro and use to
define insert and extract functions for all address types.
(arc_operands): Add operands for colon and all address
types.
---
gas/ChangeLog | 11 +++++++
gas/config/tc-arc.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++----
include/ChangeLog | 5 +++
include/opcode/arc.h | 75 +++++++++++++++++++++++++++++++++++++++++-
opcodes/ChangeLog | 10 ++++++
opcodes/arc-dis.c | 42 +++++++++++++++++++++---
opcodes/arc-opc.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 311 insertions(+), 11 deletions(-)
diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c
index 70886dd..70073f2 100644
--- a/gas/config/tc-arc.c
+++ b/gas/config/tc-arc.c
@@ -420,6 +420,9 @@ static struct hash_control *arc_reg_hash;
/* The hash table of aux register symbols. */
static struct hash_control *arc_aux_hash;
+/* The hash table of address types. */
+static struct hash_control *arc_addrtype_hash;
+
/* A table of CPU names and opcode sets. */
static const struct cpu_type
{
@@ -461,6 +464,12 @@ static const struct cpu_type
/* Used to define a bracket as operand in tokens. */
#define O_bracket O_md32
+/* Used to define a colon as an operand in tokens. */
+#define O_colon O_md31
+
+/* Used to define address types in nps400. */
+#define O_addrtype O_md30
+
/* Dummy relocation, to be sorted out. */
#define DUMMY_RELOC_ARC_ENTRY (BFD_RELOC_UNUSED + 1)
@@ -979,6 +988,8 @@ debug_exp (expressionS *t)
case O_logical_or: name = "O_logical_or"; break;
case O_index: name = "O_index"; break;
case O_bracket: name = "O_bracket"; break;
+ case O_colon: name = "O_colon"; break;
+ case O_addrtype: name = "O_addrtype"; break;
}
switch (t->X_md)
@@ -1067,6 +1078,16 @@ tokenize_arguments (char *str,
++num_args;
break;
+ case ':':
+ input_line_pointer++;
+ if (!saw_arg || num_args == ntok)
+ goto err;
+ tok->X_op = O_colon;
+ saw_arg = FALSE;
+ ++tok;
+ ++num_args;
+ break;
+
case '@':
/* We have labels, function names and relocations, all
starting with @ symbol. Sort them out. */
@@ -1693,8 +1714,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
const struct arc_operand *operand = &arc_operands[*opidx];
/* Only take input from real operands. */
- if ((operand->flags & ARC_OPERAND_FAKE)
- && !(operand->flags & ARC_OPERAND_BRAKET))
+ if (ARC_OPERAND_IS_FAKE(operand))
continue;
/* When we expect input, make sure we have it. */
@@ -1704,6 +1724,12 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
/* Match operand type with expression type. */
switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
{
+ case ARC_OPERAND_ADDRTYPE:
+ /* Check to be an address type. */
+ if (tok[tokidx].X_op != O_addrtype)
+ goto match_failed;
+ break;
+
case ARC_OPERAND_IR:
/* Check to be a register. */
if ((tok[tokidx].X_op != O_register
@@ -1755,6 +1781,12 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
goto match_failed;
break;
+ case ARC_OPERAND_COLON:
+ /* Check if colon is also in opcode table as operand. */
+ if (tok[tokidx].X_op != O_colon)
+ goto match_failed;
+ break;
+
case ARC_OPERAND_LIMM:
case ARC_OPERAND_SIGNED:
case ARC_OPERAND_UNSIGNED:
@@ -2461,6 +2493,22 @@ declare_register_set (void)
}
}
+/* Construct a symbol for an address type. */
+
+static void
+declare_addrtype (const char *name, int number)
+{
+ const char *err;
+ symbolS *addrtypeS = symbol_create (name, undefined_section,
+ number, &zero_address_frag);
+
+ err = hash_insert (arc_addrtype_hash, S_GET_NAME(addrtypeS),
+ (void *) addrtypeS);
+ if (err)
+ as_fatal (_("Inserting \"%s\" into address type table failed: %s"),
+ name, err);
+}
+
/* Port-specific assembler initialization. This function is called
once, at assembler startup time. */
@@ -2575,6 +2623,28 @@ md_begin (void)
as_fatal (_("internal error: can't hash aux register '%s': %s"),
auxr->name, retval);
}
+
+ /* Address type declaration. */
+ arc_addrtype_hash = hash_new ();
+ if (arc_addrtype_hash == NULL)
+ as_fatal (_("Virtual memory exhausted"));
+
+ declare_addrtype ("bd", ARC_NPS400_ADDRTYPE_BD);
+ declare_addrtype ("jid", ARC_NPS400_ADDRTYPE_JID);
+ declare_addrtype ("lbd", ARC_NPS400_ADDRTYPE_LBD);
+ declare_addrtype ("mbd", ARC_NPS400_ADDRTYPE_MBD);
+ declare_addrtype ("sd", ARC_NPS400_ADDRTYPE_SD);
+ declare_addrtype ("sm", ARC_NPS400_ADDRTYPE_SM);
+ declare_addrtype ("xa", ARC_NPS400_ADDRTYPE_XA);
+ declare_addrtype ("xd", ARC_NPS400_ADDRTYPE_XD);
+ declare_addrtype ("cd", ARC_NPS400_ADDRTYPE_CD);
+ declare_addrtype ("cbd", ARC_NPS400_ADDRTYPE_CBD);
+ declare_addrtype ("cjid", ARC_NPS400_ADDRTYPE_CJID);
+ declare_addrtype ("clbd", ARC_NPS400_ADDRTYPE_CLBD);
+ declare_addrtype ("cm", ARC_NPS400_ADDRTYPE_CM);
+ declare_addrtype ("csd", ARC_NPS400_ADDRTYPE_CSD);
+ declare_addrtype ("cxa", ARC_NPS400_ADDRTYPE_CXA);
+ declare_addrtype ("cxd", ARC_NPS400_ADDRTYPE_CXD);
}
/* Write a value out to the object file, using the appropriate
@@ -3254,7 +3324,7 @@ arc_parse_name (const char *name,
if (!assembling_insn)
return FALSE;
- /* Handle only registers. */
+ /* Handle only registers and address types. */
if (e->X_op != O_absent)
return FALSE;
@@ -3265,6 +3335,15 @@ arc_parse_name (const char *name,
e->X_add_number = S_GET_VALUE (sym);
return TRUE;
}
+
+ sym = hash_find (arc_addrtype_hash, name);
+ if (sym)
+ {
+ e->X_op = O_addrtype;
+ e->X_add_number = S_GET_VALUE (sym);
+ return TRUE;
+ }
+
return FALSE;
}
@@ -3726,8 +3805,7 @@ assemble_insn (const struct arc_opcode *opcode,
const struct arc_operand *operand = &arc_operands[*argidx];
const expressionS *t = (const expressionS *) 0;
- if ((operand->flags & ARC_OPERAND_FAKE)
- && !(operand->flags & ARC_OPERAND_BRAKET))
+ if (ARC_OPERAND_IS_FAKE(operand))
continue;
if (operand->flags & ARC_OPERAND_DUPLICATE)
@@ -3764,7 +3842,9 @@ assemble_insn (const struct arc_opcode *opcode,
break;
case O_bracket:
- /* Ignore brackets. */
+ case O_colon:
+ case O_addrtype:
+ /* Ignore brackets, colons, and address types. */
break;
case O_absent:
diff --git a/include/opcode/arc.h b/include/opcode/arc.h
index f0fefbb..f3fafe0 100644
--- a/include/opcode/arc.h
+++ b/include/opcode/arc.h
@@ -336,11 +336,24 @@ extern const unsigned arc_NToperand;
/* Mark the braket possition. */
#define ARC_OPERAND_BRAKET 0x1000
+/* Address type operand for NPS400. */
+#define ARC_OPERAND_ADDRTYPE 0x2000
+
+/* Mark the colon position. */
+#define ARC_OPERAND_COLON 0x4000
+
/* Mask for selecting the type for typecheck purposes. */
#define ARC_OPERAND_TYPECHECK_MASK \
(ARC_OPERAND_IR | \
ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED | \
- ARC_OPERAND_UNSIGNED | ARC_OPERAND_BRAKET)
+ ARC_OPERAND_UNSIGNED | ARC_OPERAND_BRAKET | \
+ ARC_OPERAND_ADDRTYPE | ARC_OPERAND_COLON)
+
+/* Macro to determine if an operand is a fake operand. */
+#define ARC_OPERAND_IS_FAKE(op) \
+ ((operand->flags & ARC_OPERAND_FAKE) \
+ && !((operand->flags & ARC_OPERAND_BRAKET) || \
+ (operand->flags & ARC_OPERAND_COLON)))
/* The flags structure. */
struct arc_flag_operand
@@ -608,6 +621,66 @@ extern const unsigned char arg_32bit_rc[MAX_INSN_ARGS + 1];
extern const unsigned char arg_32bit_u6[MAX_INSN_ARGS + 1];
extern const unsigned char arg_32bit_limm[MAX_INSN_ARGS + 1];
+/* Address types used in the NPS-400. See page 367 of the NPS-400 CTOP
+ Instruction Set Reference Manual v2.4 for a description of address types. */
+
+typedef enum {
+ /* Addresses in memory. */
+
+ /* Buffer descriptor. */
+ ARC_NPS400_ADDRTYPE_BD,
+
+ /* Job identifier. */
+ ARC_NPS400_ADDRTYPE_JID,
+
+ /* Linked Buffer Descriptor. */
+ ARC_NPS400_ADDRTYPE_LBD,
+
+ /* Multicast Buffer Descriptor. */
+ ARC_NPS400_ADDRTYPE_MBD,
+
+ /* Summarized Address. */
+ ARC_NPS400_ADDRTYPE_SD,
+
+ /* SMEM Security Context Local Memory. */
+ ARC_NPS400_ADDRTYPE_SM,
+
+ /* Extended Address. */
+ ARC_NPS400_ADDRTYPE_XA,
+
+ /* Extended Summarized Address. */
+ ARC_NPS400_ADDRTYPE_XD,
+
+ /* CMEM offset addresses. */
+
+ /* On-demand Counter Descriptor. */
+ ARC_NPS400_ADDRTYPE_CD,
+
+ /* CMEM Buffer Descriptor. */
+ ARC_NPS400_ADDRTYPE_CBD,
+
+ /* CMEM Job Identifier. */
+ ARC_NPS400_ADDRTYPE_CJID,
+
+ /* CMEM Linked Buffer Descriptor. */
+ ARC_NPS400_ADDRTYPE_CLBD,
+
+ /* CMEM Offset. */
+ ARC_NPS400_ADDRTYPE_CM,
+
+ /* CMEM Summarized Address. */
+ ARC_NPS400_ADDRTYPE_CSD,
+
+ /* CMEM Extended Address. */
+ ARC_NPS400_ADDRTYPE_CXA,
+
+ /* CMEM Extended Summarized Address. */
+ ARC_NPS400_ADDRTYPE_CXD
+
+} arc_nps_address_type;
+
+#define ARC_NUM_ADDRTYPES 16
+
#ifdef __cplusplus
}
#endif
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
index 7b78bdc..a7438fd 100644
--- a/opcodes/arc-dis.c
+++ b/opcodes/arc-dis.c
@@ -85,6 +85,16 @@ static const char * const regnames[64] =
"r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
};
+static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
+{
+ "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd",
+ "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd"
+};
+
+static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1;
+
+static const char * const addrtypeunknown = "unknown";
+
/* This structure keeps track which instruction class(es)
should be ignored durring disassembling. */
@@ -653,6 +663,18 @@ get_auxreg (const struct arc_opcode *opcode,
return NULL;
}
+/* Convert a value representing an address type to a string used to refer to
+ the address type in assembly code. */
+
+static const char *
+get_addrtype (int value)
+{
+ if (value < 0 || value > addrtypenames_max)
+ return addrtypeunknown;
+
+ return addrtypenames[value];
+}
+
/* Calculate the instruction length for an instruction starting with MSB
and LSB, the most and least significant byte. The ISA_MASK is used to
filter the instructions considered to only those that are part of the
@@ -1104,8 +1126,7 @@ print_insn_arc (bfd_vma memaddr,
}
/* Only take input from real operands. */
- if ((operand->flags & ARC_OPERAND_FAKE)
- && !(operand->flags & ARC_OPERAND_BRAKET))
+ if (ARC_OPERAND_IS_FAKE(operand))
continue;
if ((operand->flags & ARC_OPERAND_IGNORE)
@@ -1113,6 +1134,12 @@ print_insn_arc (bfd_vma memaddr,
&& value == -1)
continue;
+ if (operand->flags & ARC_OPERAND_COLON)
+ {
+ (*info->fprintf_func) (info->stream, ":");
+ continue;
+ }
+
if (need_comma)
(*info->fprintf_func) (info->stream, ",");
@@ -1124,6 +1151,8 @@ print_insn_arc (bfd_vma memaddr,
continue;
}
+ need_comma = TRUE;
+
/* Print the operand as directed by the flags. */
if (operand->flags & ARC_OPERAND_IR)
{
@@ -1172,6 +1201,13 @@ print_insn_arc (bfd_vma memaddr,
else
(*info->fprintf_func) (info->stream, "%d", value);
}
+ else if (operand->flags & ARC_OPERAND_ADDRTYPE)
+ {
+ const char *addrtype = get_addrtype (value);
+ (*info->fprintf_func) (info->stream, "%s", addrtype);
+ /* A colon follow an address type. */
+ need_comma = FALSE;
+ }
else
{
if (operand->flags & ARC_OPERAND_TRUNCATE
@@ -1189,8 +1225,6 @@ print_insn_arc (bfd_vma memaddr,
(*info->fprintf_func) (info->stream, "%#x", value);
}
}
-
- need_comma = TRUE;
}
return insn_len;
diff --git a/opcodes/arc-opc.c b/opcodes/arc-opc.c
index ad50ebc..111e01d 100644
--- a/opcodes/arc-opc.c
+++ b/opcodes/arc-opc.c
@@ -1160,6 +1160,42 @@ extract_nps_min_hofs (unsigned insn ATTRIBUTE_UNUSED,
return value * 16;
}
+#define MAKE_INSERT_NPS_ADDRTYPE(NAME,VALUE) \
+static unsigned \
+insert_nps_##NAME (unsigned insn ATTRIBUTE_UNUSED, \
+ int value ATTRIBUTE_UNUSED, \
+ const char **errmsg ATTRIBUTE_UNUSED) \
+{ \
+ if (value != ARC_NPS400_ADDRTYPE_##VALUE) \
+ *errmsg = _("Invalid address type for operand"); \
+ return insn; \
+} \
+ \
+static int \
+extract_nps_##NAME (unsigned insn ATTRIBUTE_UNUSED, \
+ bfd_boolean * invalid ATTRIBUTE_UNUSED) \
+{ \
+ return ARC_NPS400_ADDRTYPE_##VALUE; \
+}
+
+MAKE_INSERT_NPS_ADDRTYPE(bd, BD)
+MAKE_INSERT_NPS_ADDRTYPE(jid, JID)
+MAKE_INSERT_NPS_ADDRTYPE(lbd, LBD)
+MAKE_INSERT_NPS_ADDRTYPE(mbd, MBD)
+MAKE_INSERT_NPS_ADDRTYPE(sd, SD)
+MAKE_INSERT_NPS_ADDRTYPE(sm, SM)
+MAKE_INSERT_NPS_ADDRTYPE(xa, XA)
+MAKE_INSERT_NPS_ADDRTYPE(xd, XD)
+MAKE_INSERT_NPS_ADDRTYPE(cd, CD)
+MAKE_INSERT_NPS_ADDRTYPE(cbd, CBD)
+MAKE_INSERT_NPS_ADDRTYPE(cjid, CJID)
+MAKE_INSERT_NPS_ADDRTYPE(clbd, CLBD)
+MAKE_INSERT_NPS_ADDRTYPE(cm, CM)
+MAKE_INSERT_NPS_ADDRTYPE(csd, CSD)
+MAKE_INSERT_NPS_ADDRTYPE(cxa, CXA)
+MAKE_INSERT_NPS_ADDRTYPE(cxd, CXD)
+
+
/* Include the generic extract/insert functions. Order is important
as some of the functions present in the .h may be disabled via
defines. */
@@ -2081,6 +2117,57 @@ const struct arc_operand arc_operands[] =
#define NPS_E4BY_INDEX3 (NPS_E4BY_INDEX2 + 1)
{ 2, 0, 0, ARC_OPERAND_UNSIGNED | ARC_OPERAND_NCHK, insert_nps_index3, extract_nps_index3 },
+
+#define COLON (NPS_E4BY_INDEX3 + 1)
+ { 0, 0, 0, ARC_OPERAND_COLON | ARC_OPERAND_FAKE, NULL, NULL },
+
+#define NPS_BD (COLON + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_bd, extract_nps_bd },
+
+#define NPS_JID (NPS_BD + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_jid, extract_nps_jid },
+
+#define NPS_LBD (NPS_JID + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_lbd, extract_nps_lbd },
+
+#define NPS_MBD (NPS_LBD + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_mbd, extract_nps_mbd },
+
+#define NPS_SD (NPS_MBD + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_sd, extract_nps_sd },
+
+#define NPS_SM (NPS_SD + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_sm, extract_nps_sm },
+
+#define NPS_XA (NPS_SM + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_xa, extract_nps_xa },
+
+#define NPS_XD (NPS_XA + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_xd, extract_nps_xd },
+
+#define NPS_CD (NPS_XD + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_cd, extract_nps_cd },
+
+#define NPS_CBD (NPS_CD + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_cbd, extract_nps_cbd },
+
+#define NPS_CJID (NPS_CBD + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_cjid, extract_nps_cjid },
+
+#define NPS_CLBD (NPS_CJID + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_clbd, extract_nps_clbd },
+
+#define NPS_CM (NPS_CLBD + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_cm, extract_nps_cm },
+
+#define NPS_CSD (NPS_CM + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_csd, extract_nps_csd },
+
+#define NPS_CXA (NPS_CSD + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_cxa, extract_nps_cxa },
+
+#define NPS_CXD (NPS_CXA + 1)
+ { 0, 0, 0, ARC_OPERAND_ADDRTYPE | ARC_OPERAND_NCHK, insert_nps_cxd, extract_nps_cxd },
};
const unsigned arc_num_operands = ARRAY_SIZE (arc_operands);
--
2.7.4