summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorClaudiu Zissulescu <claziss@synopsys.com>2016-04-06 16:08:04 +0200
committerClaudiu Zissulescu <claziss@synopsys.com>2016-04-12 10:21:06 +0200
commitf36e33dac1a97cca8f79ca8b20cf0fb05f1e25f4 (patch)
tree36f13760bc5525172fce20159ffd3500e5ad17fd /gas
parent1c2e355e4830814e18329a53d01cfa634d576211 (diff)
downloadbinutils-gdb-f36e33dac1a97cca8f79ca8b20cf0fb05f1e25f4.tar.gz
Add support for .extCondCode, .extCoreRegister and .extAuxRegister.
gas/ 2016-04-05 Claudiu Zissulescu <claziss@synopsys.com> * testsuite/gas/arc/textauxregister.d: New file. * testsuite/gas/arc/textauxregister.s: Likewise. * testsuite/gas/arc/textcondcode.d: Likewise. * testsuite/gas/arc/textcondcode.s: Likewise. * testsuite/gas/arc/textcoreregister.d: Likewise. * testsuite/gas/arc/textcoreregister.s: Likewise. * testsuite/gas/arc/textpseudoop.d: Likewise. * testsuite/gas/arc/textpseudoop.s: Likewise. * testsuite/gas/arc/ld2.d: Update test. * testsuite/gas/arc/st.d: Likewise. * testsuite/gas/arc/taux.d: Likewise. * doc/c-arc.texi (ARC Directives): Add .extCondCode, .extCoreRegister and .extAuxRegister documentation. * config/tc-arc.c (arc_extcorereg): New function. (md_pseudo_table): Add .extCondCode, .extCoreRegister and .extAuxRegister pseudo-ops. (extRegister_t): New type. (ext_condcode, arc_aux_hash): New global variable. (find_opcode_match): Check for extensions. (preprocess_operands): Likewise. (md_begin): Add aux registers in a hash. (assemble_insn): Update use arc_flags member. (tokenize_extregister): New function. (create_extcore_section): Likewise. * config/tc-arc.h (MAX_FLAG_NAME_LENGHT): Increase to 10. (arc_flags): Delete code, add flgp. include/ 2016-04-05 Claudiu Zissulescu <claziss@synopsys.com> * opcode/arc.h (flag_class_t): Update. (ARC_OPCODE_NONE): Define. (ARC_OPCODE_ARCALL): Likewise. (ARC_OPCODE_ARCFPX): Likewise. (ARC_REGISTER_READONLY): Likewise. (ARC_REGISTER_WRITEONLY): Likewise. (ARC_REGISTER_NOSHORT_CUT): Likewise. (arc_aux_reg): Add cpu. opcodes/ 2016-04-05 Claudiu Zissulescu <claziss@synopsys.com> * arc-dis.c (find_format): Check for extension flags. (print_flags): New function. (print_insn_arc): Update for .extCondCode, .extCoreRegister and .extAuxRegister. * arc-ext.c (arcExtMap_coreRegName): Use LAST_EXTENSION_CORE_REGISTER. (arcExtMap_coreReadWrite): Likewise. (dump_ARC_extmap): Update printing. * arc-opc.c (arc_flag_classes): Add F_CLASS_EXTEND flag. (arc_aux_regs): Add cpu field. * arc-regs.h: Add cpu field, lower case name aux registers. Signed-off-by: Claudiu Zissulescu <claziss@synopsys.com>
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog28
-rw-r--r--gas/NEWS4
-rw-r--r--gas/config/tc-arc.c364
-rw-r--r--gas/config/tc-arc.h4
-rw-r--r--gas/doc/c-arc.texi82
-rw-r--r--gas/testsuite/gas/arc/ld2.d4
-rw-r--r--gas/testsuite/gas/arc/st.d2
-rw-r--r--gas/testsuite/gas/arc/taux.d9
-rw-r--r--gas/testsuite/gas/arc/textauxregister.d12
-rw-r--r--gas/testsuite/gas/arc/textauxregister.s6
-rw-r--r--gas/testsuite/gas/arc/textcondcode.d13
-rw-r--r--gas/testsuite/gas/arc/textcondcode.s8
-rw-r--r--gas/testsuite/gas/arc/textcoreregister.d12
-rw-r--r--gas/testsuite/gas/arc/textcoreregister.s7
-rw-r--r--gas/testsuite/gas/arc/textpseudoop.d11
-rw-r--r--gas/testsuite/gas/arc/textpseudoop.s11
16 files changed, 540 insertions, 37 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 5f93283093a..827130fc671 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,33 @@
2016-04-12 Claudiu Zissulescu <claziss@synopsys.com>
+ * testsuite/gas/arc/textauxregister.d: New file.
+ * testsuite/gas/arc/textauxregister.s: Likewise.
+ * testsuite/gas/arc/textcondcode.d: Likewise.
+ * testsuite/gas/arc/textcondcode.s: Likewise.
+ * testsuite/gas/arc/textcoreregister.d: Likewise.
+ * testsuite/gas/arc/textcoreregister.s: Likewise.
+ * testsuite/gas/arc/textpseudoop.d: Likewise.
+ * testsuite/gas/arc/textpseudoop.s: Likewise.
+ * testsuite/gas/arc/ld2.d: Update test.
+ * testsuite/gas/arc/st.d: Likewise.
+ * testsuite/gas/arc/taux.d: Likewise.
+ * doc/c-arc.texi (ARC Directives): Add .extCondCode,
+ .extCoreRegister and .extAuxRegister documentation.
+ * config/tc-arc.c (arc_extcorereg): New function.
+ (md_pseudo_table): Add .extCondCode, .extCoreRegister and
+ .extAuxRegister pseudo-ops.
+ (extRegister_t): New type.
+ (ext_condcode, arc_aux_hash): New global variable.
+ (find_opcode_match): Check for extensions.
+ (preprocess_operands): Likewise.
+ (md_begin): Add aux registers in a hash.
+ (assemble_insn): Update use arc_flags member.
+ (tokenize_extregister): New function.
+ (create_extcore_section): Likewise.
+ * config/tc-arc.h (arc_flags): Delete code, add flgp.
+
+2016-04-12 Claudiu Zissulescu <claziss@synopsys.com>
+
* testsuite/gas/arc/noargs_a7.d: New file.
* testsuite/gas/arc/noargs_a7.s: Likewise.
* testsuite/gas/arc/noargs_hs.d: Likewise.
diff --git a/gas/NEWS b/gas/NEWS
index a627028de15..2f5e88daff9 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,4 +1,8 @@
-*- text -*-
+* ARC backend accepts .extInstruction, .extCondCode, .extAuxRegister, and
+ .extCoreRegister pseudo-ops that allow an user to define custom
+ instructions, conditional codes, auxiliary and core registers.
+
* Add a configure option --enable-elf-stt-common to decide whether ELF
assembler should generate common symbols with the STT_COMMON type by
default. Default to no.
diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c
index 3aeedb1943a..7486924ae84 100644
--- a/gas/config/tc-arc.c
+++ b/gas/config/tc-arc.c
@@ -140,6 +140,7 @@ static void arc_lcomm (int);
static void arc_option (int);
static void arc_extra_reloc (int);
static void arc_extinsn (int);
+static void arc_extcorereg (int);
const pseudo_typeS md_pseudo_table[] =
{
@@ -151,7 +152,10 @@ const pseudo_typeS md_pseudo_table[] =
{ "lcommon", arc_lcomm, 0 },
{ "cpu", arc_option, 0 },
- { "extinstruction", arc_extinsn, 0 },
+ { "extinstruction", arc_extinsn, 0 },
+ { "extcoreregister", arc_extcorereg, EXT_CORE_REGISTER },
+ { "extauxregister", arc_extcorereg, EXT_AUX_REGISTER },
+ { "extcondcode", arc_extcorereg, EXT_COND_CODE },
{ "tls_gd_ld", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
{ "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
@@ -343,6 +347,21 @@ static const attributes_t syntaxclassmod[] =
{ "OP1_MUST_BE_IMM" , 15, ARC_OP1_MUST_BE_IMM }
};
+/* Extension register type. */
+typedef struct
+{
+ char *name;
+ int number;
+ int imode;
+} extRegister_t;
+
+/* A structure to hold the additional conditional codes. */
+static struct
+{
+ struct arc_flag_operand *arc_ext_condcode;
+ int size;
+} ext_condcode = { NULL, 0 };
+
/* Structure to hold an entry in ARC_OPCODE_HASH. */
struct arc_opcode_hash_entry
{
@@ -386,6 +405,9 @@ static struct hash_control *arc_opcode_hash;
/* The hash table of register symbols. */
static struct hash_control *arc_reg_hash;
+/* The hash table of aux register symbols. */
+static struct hash_control *arc_aux_hash;
+
/* A table of CPU names and opcode sets. */
static const struct cpu_type
{
@@ -1658,31 +1680,23 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
case O_symbol:
{
const char *p;
- size_t len;
const struct arc_aux_reg *auxr;
- unsigned j;
if (opcode->class != AUXREG)
goto de_fault;
p = S_GET_NAME (tok[tokidx].X_add_symbol);
- len = strlen (p);
-
- auxr = &arc_aux_regs[0];
- for (j = 0; j < arc_num_aux_regs; j++, auxr++)
- if (len == auxr->length
- && strcasecmp (auxr->name, p) == 0
- && ((auxr->subclass == NONE)
- || check_cpu_feature (auxr->subclass)))
- {
- /* We modify the token array here, safe in the
- knowledge, that if this was the wrong choice
- then the original contents will be restored
- from BKTOK. */
- tok[tokidx].X_op = O_constant;
- tok[tokidx].X_add_number = auxr->address;
- ARC_SET_FLAG (tok[tokidx].X_add_symbol, ARC_FLAG_AUX);
- break;
- }
+
+ auxr = hash_find (arc_aux_hash, p);
+ if (auxr)
+ {
+ /* We modify the token array here, safe in the
+ knowledge, that if this was the wrong
+ choice then the original contents will be
+ restored from BKTOK. */
+ tok[tokidx].X_op = O_constant;
+ tok[tokidx].X_add_number = auxr->address;
+ ARC_SET_FLAG (tok[tokidx].X_add_symbol, ARC_FLAG_AUX);
+ }
if (tok[tokidx].X_op != O_constant)
goto de_fault;
@@ -1809,7 +1823,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
/* Setup ready for flag parsing. */
lnflg = nflgs;
for (i = 0; i < nflgs; i++)
- first_pflag [i].code = 0;
+ first_pflag[i].flgp = NULL;
/* Check the flags. Iterate over the valid flag classes. */
for (flgidx = opcode->flags; *flgidx; ++flgidx)
@@ -1818,31 +1832,57 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
const unsigned *flgopridx;
int cl_matches = 0;
+ struct arc_flags *pflag = NULL;
+
+ /* Check for extension conditional codes. */
+ if (ext_condcode.arc_ext_condcode
+ && cl_flags->class & F_CLASS_EXTEND)
+ {
+ struct arc_flag_operand *pf = ext_condcode.arc_ext_condcode;
+ while (pf->name)
+ {
+ pflag = first_pflag;
+ for (i = 0; i < nflgs; i++, pflag++)
+ {
+ if (!strcmp (pf->name, pflag->name))
+ {
+ if (pflag->flgp != NULL)
+ goto match_failed;
+ /* Found it. */
+ cl_matches++;
+ pflag->flgp = pf;
+ lnflg--;
+ break;
+ }
+ }
+ pf++;
+ }
+ }
for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
{
const struct arc_flag_operand *flg_operand;
- struct arc_flags *pflag = first_pflag;
+ pflag = first_pflag;
flg_operand = &arc_flag_operands[*flgopridx];
for (i = 0; i < nflgs; i++, pflag++)
{
/* Match against the parsed flags. */
if (!strcmp (flg_operand->name, pflag->name))
{
- if (pflag->code != 0)
+ if (pflag->flgp != NULL)
goto match_failed;
cl_matches++;
- pflag->code = *flgopridx;
+ pflag->flgp = (struct arc_flag_operand *) flg_operand;
lnflg--;
break; /* goto next flag class and parsed flag. */
}
}
}
- if (cl_flags->class == F_CLASS_REQUIRED && cl_matches == 0)
+ if ((cl_flags->class & F_CLASS_REQUIRED) && cl_matches == 0)
goto match_failed;
- if (cl_flags->class == F_CLASS_OPTIONAL && cl_matches > 1)
+ if ((cl_flags->class & F_CLASS_OPTIONAL) && cl_matches > 1)
goto match_failed;
}
/* Did I check all the parsed flags? */
@@ -2345,6 +2385,30 @@ md_begin (void)
/* Initialize the last instructions. */
memset (&arc_last_insns[0], 0, sizeof (arc_last_insns));
+
+ /* Aux register declaration. */
+ arc_aux_hash = hash_new ();
+ if (arc_aux_hash == NULL)
+ as_fatal (_("Virtual memory exhausted"));
+
+ const struct arc_aux_reg *auxr = &arc_aux_regs[0];
+ unsigned int i;
+ for (i = 0; i < arc_num_aux_regs; i++, auxr++)
+ {
+ const char *retval;
+
+ if (!(auxr->cpu & arc_target))
+ continue;
+
+ if ((auxr->subclass != NONE)
+ && !check_cpu_feature (auxr->subclass))
+ continue;
+
+ retval = hash_insert (arc_aux_hash, auxr->name, (void *) auxr);
+ if (retval)
+ as_fatal (_("internal error: can't hash aux register '%s': %s"),
+ auxr->name, retval);
+ }
}
/* Write a value out to the object file, using the appropriate
@@ -3631,8 +3695,7 @@ assemble_insn (const struct arc_opcode *opcode,
/* Handle flags. */
for (i = 0; i < nflg; i++)
{
- const struct arc_flag_operand *flg_operand =
- &arc_flag_operands[pflags[i].code];
+ const struct arc_flag_operand *flg_operand = pflags[i].flgp;
/* Check if the instruction has a delay slot. */
if (!strcmp (flg_operand->name, "d"))
@@ -4194,6 +4257,249 @@ arc_extinsn (int ignore ATTRIBUTE_UNUSED)
create_extinst_section (&einsn);
}
+static void
+tokenize_extregister (extRegister_t *ereg, int opertype)
+{
+ char *name;
+ char *mode;
+ char c;
+ char *p;
+ int number, imode = 0;
+ bfd_boolean isCore_p = (opertype == EXT_CORE_REGISTER) ? TRUE : FALSE;
+ bfd_boolean isReg_p = (opertype == EXT_CORE_REGISTER
+ || opertype == EXT_AUX_REGISTER) ? TRUE : FALSE;
+
+ /* 1st: get register name. */
+ SKIP_WHITESPACE ();
+ p = input_line_pointer;
+ c = get_symbol_name (&p);
+
+ name = xstrdup (p);
+ restore_line_pointer (c);
+
+ /* 2nd: get register number. */
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("expected comma after register name"));
+ ignore_rest_of_line ();
+ free (name);
+ return;
+ }
+ input_line_pointer++;
+ number = get_absolute_expression ();
+
+ if (number < 0)
+ {
+ as_bad (_("negative operand number %d"), number);
+ ignore_rest_of_line ();
+ free (name);
+ return;
+ }
+
+ if (isReg_p)
+ {
+ /* 3rd: get register mode. */
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("expected comma after register number"));
+ ignore_rest_of_line ();
+ free (name);
+ return;
+ }
+
+ input_line_pointer++;
+ mode = input_line_pointer;
+
+ if (!strncmp (mode, "r|w", 3))
+ {
+ imode = 0;
+ input_line_pointer += 3;
+ }
+ else if (!strncmp (mode, "r", 1))
+ {
+ imode = ARC_REGISTER_READONLY;
+ input_line_pointer += 1;
+ }
+ else if (strncmp (mode, "w", 1))
+ {
+ as_bad (_("invalid mode"));
+ ignore_rest_of_line ();
+ free (name);
+ return;
+ }
+ else
+ {
+ imode = ARC_REGISTER_WRITEONLY;
+ input_line_pointer += 1;
+ }
+ }
+
+ if (isCore_p)
+ {
+ /* 4th: get core register shortcut. */
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("expected comma after register mode"));
+ ignore_rest_of_line ();
+ free (name);
+ return;
+ }
+
+ input_line_pointer++;
+
+ if (!strncmp (input_line_pointer, "cannot_shortcut", 15))
+ {
+ imode |= ARC_REGISTER_NOSHORT_CUT;
+ input_line_pointer += 15;
+ }
+ else if (strncmp (input_line_pointer, "can_shortcut", 12))
+ {
+ as_bad (_("shortcut designator invalid"));
+ ignore_rest_of_line ();
+ free (name);
+ return;
+ }
+ else
+ {
+ input_line_pointer += 12;
+ }
+ }
+ demand_empty_rest_of_line ();
+
+ ereg->name = name;
+ ereg->number = number;
+ ereg->imode = imode;
+}
+
+/* Create an extension register/condition description in the arc
+ extension section of the output file.
+
+ The structure for an instruction is like this:
+ [0]: Length of the record.
+ [1]: Type of the record.
+
+ For core regs and condition codes:
+ [2]: Value.
+ [3]+ Name.
+
+ For auxilirary registers:
+ [2..5]: Value.
+ [6]+ Name
+
+ The sequence is terminated by an empty entry. */
+
+static void
+create_extcore_section (extRegister_t *ereg, int opertype)
+{
+ segT old_sec = now_seg;
+ int old_subsec = now_subseg;
+ char *p;
+ int name_len = strlen (ereg->name);
+
+ arc_set_ext_seg ();
+
+ switch (opertype)
+ {
+ case EXT_COND_CODE:
+ case EXT_CORE_REGISTER:
+ p = frag_more (1);
+ *p = 3 + name_len + 1;
+ p = frag_more (1);
+ *p = opertype;
+ p = frag_more (1);
+ *p = ereg->number;
+ break;
+ case EXT_AUX_REGISTER:
+ p = frag_more (1);
+ *p = 6 + name_len + 1;
+ p = frag_more (1);
+ *p = EXT_AUX_REGISTER;
+ p = frag_more (1);
+ *p = (ereg->number >> 24) & 0xff;
+ p = frag_more (1);
+ *p = (ereg->number >> 16) & 0xff;
+ p = frag_more (1);
+ *p = (ereg->number >> 8) & 0xff;
+ p = frag_more (1);
+ *p = (ereg->number) & 0xff;
+ break;
+ default:
+ break;
+ }
+
+ p = frag_more (name_len + 1);
+ strcpy (p, ereg->name);
+
+ subseg_set (old_sec, old_subsec);
+}
+
+/* Handler .extCoreRegister pseudo-op. */
+
+static void
+arc_extcorereg (int opertype)
+{
+ extRegister_t ereg;
+ struct arc_aux_reg *auxr;
+ const char *retval;
+ struct arc_flag_operand *ccode;
+
+ memset (&ereg, 0, sizeof (ereg));
+ tokenize_extregister (&ereg, opertype);
+
+ switch (opertype)
+ {
+ case EXT_CORE_REGISTER:
+ /* Core register. */
+ if (ereg.number > 60)
+ as_bad (_("core register %s value (%d) too large"), ereg.name,
+ ereg.number);
+ declare_register (ereg.name, ereg.number);
+ break;
+ case EXT_AUX_REGISTER:
+ /* Auxiliary register. */
+ auxr = xmalloc (sizeof (struct arc_aux_reg));
+ auxr->name = ereg.name;
+ auxr->cpu = arc_target;
+ auxr->subclass = NONE;
+ auxr->address = ereg.number;
+ retval = hash_insert (arc_aux_hash, auxr->name, (void *) auxr);
+ if (retval)
+ as_fatal (_("internal error: can't hash aux register '%s': %s"),
+ auxr->name, retval);
+ break;
+ case EXT_COND_CODE:
+ /* Condition code. */
+ if (ereg.number > 31)
+ as_bad (_("condition code %s value (%d) too large"), ereg.name,
+ ereg.number);
+ ext_condcode.size ++;
+ ext_condcode.arc_ext_condcode =
+ xrealloc (ext_condcode.arc_ext_condcode,
+ (ext_condcode.size + 1) * sizeof (struct arc_flag_operand));
+ if (ext_condcode.arc_ext_condcode == NULL)
+ as_fatal (_("Virtual memory exhausted"));
+
+ ccode = ext_condcode.arc_ext_condcode + ext_condcode.size - 1;
+ ccode->name = ereg.name;
+ ccode->code = ereg.number;
+ ccode->bits = 5;
+ ccode->shift = 0;
+ ccode->favail = 0; /* not used. */
+ ccode++;
+ memset (ccode, 0, sizeof (struct arc_flag_operand));
+ break;
+ default:
+ as_bad (_("Unknown extension"));
+ break;
+ }
+ create_extcore_section (&ereg, opertype);
+}
+
/* Local variables:
eval: (c-set-style "gnu")
indent-tabs-mode: t
diff --git a/gas/config/tc-arc.h b/gas/config/tc-arc.h
index 54fa60174de..16f6a0686f4 100644
--- a/gas/config/tc-arc.h
+++ b/gas/config/tc-arc.h
@@ -224,8 +224,8 @@ struct arc_flags
/* Name of the parsed flag. */
char name[MAX_FLAG_NAME_LENGTH + 1];
- /* The code of the parsed flag. Valid when is not zero. */
- unsigned char code;
+ /* Pointer to arc flags. */
+ struct arc_flag_operand *flgp;
};
extern const relax_typeS md_relax_table[];
diff --git a/gas/doc/c-arc.texi b/gas/doc/c-arc.texi
index a2372858053..a3e18cfd2a8 100644
--- a/gas/doc/c-arc.texi
+++ b/gas/doc/c-arc.texi
@@ -335,11 +335,11 @@ two. If no alignment is specified, as will set the alignment to the
largest power of two less than or equal to the size of the symbol, up
to a maximum of 16.
-@cindex @code{lcommon} directive
+@cindex @code{lcommon} directive, ARC
@item .lcommon @var{symbol}, @var{length}[, @var{alignment}]
The same as @code{lcomm} directive.
-@cindex @code{cpu} directive
+@cindex @code{cpu} directive, ARC
@item .cpu @var{cpu}
The @code{.cpu} directive must be followed by the desired core
version. Permitted values for CPU are:
@@ -362,8 +362,84 @@ Note: the @code{.cpu} directive overrides the command line option
@code{-mcpu=@var{cpu}}; a warning is emitted when the version is not
consistent between the two.
+@item .extAuxRegister @var{name}, @var{addr}, @var{mode}
+@cindex @code{extAuxRegister} directive, ARC
+Auxiliary registers can be defined in the assembler source code by
+using this directive. The first parameter, @var{name}, is the name of the
+new auxiliary register. The second parameter, @var{addr}, is
+address the of the auxiliary register. The third parameter,
+@var{mode}, specifies whether the register is readable and/or writable
+and is one of:
+@table @code
+@item r
+Read only;
+
+@item w
+Write only;
+
+@item r|w
+Read and write.
+
+@end table
+
+For example:
+@example
+ .extAuxRegister mulhi, 0x12, w
+@end example
+specifies a write only extension auxiliary register, @var{mulhi} at
+address 0x12.
+
+@item .extCondCode @var{suffix}, @var{val}
+@cindex @code{extCondCode} directive, ARC
+ARC supports extensible condition codes. This directive defines a new
+condition code, to be known by the suffix, @var{suffix} and will
+depend on the value, @var{val} in the condition code.
+
+For example:
+@example
+ .extCondCode is_busy,0x14
+ add.is_busy r1,r2,r3
+@end example
+will only execute the @code{add} instruction if the condition code
+value is 0x14.
+
+@item .extCoreRegister @var{name}, @var{regnum}, @var{mode}, @var{shortcut}
+@cindex @code{extCoreRegister} directive, ARC
+Specifies an extension core register named @var{name} as a synonym for
+the register numbered @var{regnum}. The register number must be
+between 32 and 59. The third argument, @var{mode}, indicates whether
+the register is readable and/or writable and is one of:
+@table @code
+@item r
+Read only;
+
+@item w
+Write only;
+
+@item r|w
+Read and write.
+
+@end table
+
+The final parameter, @var{shortcut} indicates whether the register has
+a short cut in the pipeline. The valid values are:
+@table @code
+@item can_shortcut
+The register has a short cut in the pipeline;
+
+@item cannot_shortcut
+The register does not have a short cut in the pipeline.
+@end table
+
+For example:
+@example
+ .extCoreRegister mlo, 57, r , can_shortcut
+@end example
+defines a read only extension core register, @code{mlo}, which is
+register 57, and can short cut the pipeline.
+
@item .extInstruction @var{name}, @var{opcode}, @var{subopcode}, @var{suffixclass}, @var{syntaxclass}
-@cindex @code{extInstruction} directive
+@cindex @code{extInstruction} directive, ARC
ARC allows the user to specify extension instructions. These
extension instructions are not macros; the assembler creates encodings
for use of these instructions according to the specification by the
diff --git a/gas/testsuite/gas/arc/ld2.d b/gas/testsuite/gas/arc/ld2.d
index c2f6b1fe9f6..0a7874ce33d 100644
--- a/gas/testsuite/gas/arc/ld2.d
+++ b/gas/testsuite/gas/arc/ld2.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
1c: 130f 0082 ldb r2,\[r3,15\]
20: 14fe 8103 ld[hw]+ r3,\[r4,-2\]
24: 212a 0080 lr r1,\[r2\]
- 28: 216a 0500 lr r1,\[0x14\]
- 2c: 206a 0000 lr r0,\[0\]
+ 28: 216a 0500 lr r1,\[dmc_code_ram\]
+ 2c: 206a 0000 lr r0,\[status\]
diff --git a/gas/testsuite/gas/arc/st.d b/gas/testsuite/gas/arc/st.d
index 4e2ebba7b6f..3f75d40c367 100644
--- a/gas/testsuite/gas/arc/st.d
+++ b/gas/testsuite/gas/arc/st.d
@@ -27,4 +27,4 @@ Disassembly of section .text:
50: 262b 7080 0000 0064 sr 0x64,\[r2\]
58: 212b 0f80 0000 2710 sr r1,\[0x2710\]
60: 266b 7fc0 0000 0064 sr 0x64,\[0x3f\]
- 68: 26ab 7901 0000 2710 sr 0x2710,\[100\]
+ 68: 26ab 7901 0000 2710 sr 0x2710,\[vbfdw_build\]
diff --git a/gas/testsuite/gas/arc/taux.d b/gas/testsuite/gas/arc/taux.d
index 6759d734a48..10f50ee08c0 100644
--- a/gas/testsuite/gas/arc/taux.d
+++ b/gas/testsuite/gas/arc/taux.d
@@ -3,6 +3,9 @@
#source: taux.s
# Most of the AUX rgisters are defined for all ARC variants besides the
# FPX/FPUDA registers which should end as undefined when assemble generic.
+.* U arc600_build_config
+.* U aux_crc_mode
+.* U aux_crc_poly
.* U aux_dpfp1h
.* U aux_dpfp1l
.* U aux_dpfp2h
@@ -13,4 +16,10 @@
.* U d2l
.* U dpfp_status
.* U fp_status
+.* mx0
+.* mx1
+.* my0
+.* my1
+.* scratch_a
+.* tsch
#pass
diff --git a/gas/testsuite/gas/arc/textauxregister.d b/gas/testsuite/gas/arc/textauxregister.d
new file mode 100644
index 00000000000..8a0d77ecba0
--- /dev/null
+++ b/gas/testsuite/gas/arc/textauxregister.d
@@ -0,0 +1,12 @@
+#as: -mcpu=arcem
+#objdump: -dr
+
+.*: +file format .*arc.*
+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.text>:
+ 0: 2067 0c00 aex r0,\[mlx\]
+ 4: 216a 0c40 lr r1,\[mly\]
+ 8: 266b 7c00 0000 0012 sr 0x12,\[mlx\]
diff --git a/gas/testsuite/gas/arc/textauxregister.s b/gas/testsuite/gas/arc/textauxregister.s
new file mode 100644
index 00000000000..8b56ea363cd
--- /dev/null
+++ b/gas/testsuite/gas/arc/textauxregister.s
@@ -0,0 +1,6 @@
+ .extAuxRegister mlx, 0x30, r|w
+ .extAuxRegister mly, 0x31, r|w
+
+ aex r0,[mlx]
+ lr r1,[mly]
+ sr 0x12,[mlx]
diff --git a/gas/testsuite/gas/arc/textcondcode.d b/gas/testsuite/gas/arc/textcondcode.d
new file mode 100644
index 00000000000..9671c011095
--- /dev/null
+++ b/gas/testsuite/gas/arc/textcondcode.d
@@ -0,0 +1,13 @@
+#objdump: -dr
+
+.*: +file format .*arc.*
+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.text>:
+ 0: 23c0 00ed add.hi r3,r3,0x3
+ 4: 24c0 012e add.ls r4,r4,0x4
+ 8: 25c0 016f add.pnz r5,r5,0x5
+ c: 26c0 01b2 add.cctst r6,r6,0x6
+ 10: 27c0 01f3 add.cstst r7,r7,0x7
diff --git a/gas/testsuite/gas/arc/textcondcode.s b/gas/testsuite/gas/arc/textcondcode.s
new file mode 100644
index 00000000000..d2f292df50d
--- /dev/null
+++ b/gas/testsuite/gas/arc/textcondcode.s
@@ -0,0 +1,8 @@
+ .extCondCode cctst, 0x12
+ .extCondCode cstst, 0x13
+
+ add.hi r3,r3,3
+ add.ls r4,r4,4
+ add.pnz r5,r5,5
+ add.cctst r6,r6,6
+ add.cstst r7,r7,7
diff --git a/gas/testsuite/gas/arc/textcoreregister.d b/gas/testsuite/gas/arc/textcoreregister.d
new file mode 100644
index 00000000000..36f78bb422e
--- /dev/null
+++ b/gas/testsuite/gas/arc/textcoreregister.d
@@ -0,0 +1,12 @@
+#objdump: -dr
+
+.*: +file format .*arc.*
+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.text>:
+ 0: 2000 00b8 add accX,r0,r2
+ 4: 2100 00f9 add accY,r1,r3
+ 8: 2000 70c2 add r2,accX,r3
+ c: 2100 7e38 add accX,accY,accX
diff --git a/gas/testsuite/gas/arc/textcoreregister.s b/gas/testsuite/gas/arc/textcoreregister.s
new file mode 100644
index 00000000000..607edc48694
--- /dev/null
+++ b/gas/testsuite/gas/arc/textcoreregister.s
@@ -0,0 +1,7 @@
+ .extCoreRegister accX, 56, r|w, can_shortcut
+ .extCoreRegister accY, 57, r|w, can_shortcut
+
+ add accX, r0, r2
+ add accY, r1, r3
+ add r2, accX, r3
+ add accX, accY, accX
diff --git a/gas/testsuite/gas/arc/textpseudoop.d b/gas/testsuite/gas/arc/textpseudoop.d
new file mode 100644
index 00000000000..e196e95a5ef
--- /dev/null
+++ b/gas/testsuite/gas/arc/textpseudoop.d
@@ -0,0 +1,11 @@
+#objdump: -dr
+
+.*: +file format .*arc.*
+
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.text>:
+ 0: 39da 7010 custom0.tst mlx,mlx,r0
+ 4: 392f 701b custom1 mlx,r0
+ 8: 20aa 0041 lr r0,\[aux_test\]
diff --git a/gas/testsuite/gas/arc/textpseudoop.s b/gas/testsuite/gas/arc/textpseudoop.s
new file mode 100644
index 00000000000..eb1ce30ffd1
--- /dev/null
+++ b/gas/testsuite/gas/arc/textpseudoop.s
@@ -0,0 +1,11 @@
+ .extInstruction custom0, 0x07, 0x1a, SUFFIX_COND|SUFFIX_FLAG, SYNTAX_3OP
+ .extInstruction custom1, 0x07, 0x1b, SUFFIX_FLAG, SYNTAX_2OP
+
+ .extCoreRegister mlx, 57, r|w, can_shortcut
+ .extCondCode tst, 0x10
+ .extAuxRegister aux_test, 0x41, r|w
+
+ custom0.tst mlx,mlx,r0
+ custom1 mlx,r0
+
+ lr r0, [aux_test]