Add support for .extInstruction pseudo-op.
gas/ 2016-04-04 Claudiu Zissulescu <claziss@synopsys.com> * testsuite/gas/arc/textinsn-errors.d: New File. * testsuite/gas/arc/textinsn-errors.err: Likewise. * testsuite/gas/arc/textinsn-errors.s: Likewise. * testsuite/gas/arc/textinsn2op.d: Likewise. * testsuite/gas/arc/textinsn2op.s: Likewise. * testsuite/gas/arc/textinsn2op01.d: Likewise. * testsuite/gas/arc/textinsn2op01.s: Likewise. * testsuite/gas/arc/textinsn3op.d: Likewise. * testsuite/gas/arc/textinsn3op.s: Likewise. * doc/c-arc.texi (ARC Directives): Add .extInstruction documentation. * config/tc-arc.c (arcext_section): New variable. (arc_extinsn): New function. (md_pseudo_table): Add .extInstruction pseudo op. (attributes_t): New type. (suffixclass, syntaxclass, syntaxclassmod): New constant structures. (find_opcode_match): Remove arc_num_opcodes. (md_begin): Likewise. (tokenize_extinsn): New function. (arc_set_ext_seg): Likewise. (create_extinst_section): Likewise. include/ 2016-04-04 Claudiu Zissulescu <claziss@synopsys.com> * opcode/arc.h (arc_num_opcodes): Remove. (ARC_SYNTAX_3OP, ARC_SYNTAX_2OP, ARC_OP1_MUST_BE_IMM) (ARC_OP1_IMM_IMPLIED, ARC_SUFFIX_NONE, ARC_SUFFIX_COND) (ARC_SUFFIX_FLAG): Define. (flags_none, flags_f, flags_cc, flags_ccf): Declare. (arg_none, arg_32bit_rarbrc, arg_32bit_zarbrc, arg_32bit_rbrbrc) (arg_32bit_rarbu6, arg_32bit_zarbu6, arg_32bit_rbrbu6) (arg_32bit_rbrbs12, arg_32bit_ralimmrc, arg_32bit_rarblimm) (arg_32bit_zalimmrc, arg_32bit_zarblimm, arg_32bit_rbrblimm) (arg_32bit_ralimmu6, arg_32bit_zalimmu6, arg_32bit_zalimms12) (arg_32bit_ralimmlimm, arg_32bit_zalimmlimm, arg_32bit_rbrc) (arg_32bit_zarc, arg_32bit_rbu6, arg_32bit_zau6, arg_32bit_rblimm) (arg_32bit_zalimm, arg_32bit_limmrc, arg_32bit_limmu6) (arg_32bit_limms12, arg_32bit_limmlimm): Likewise. opcodes/ 2016-04-04 Claudiu Zissulescu <claziss@synopsys.com> * arc-opc.c (flags_none, flags_f, flags_cc, flags_ccf): Initialize. (arg_none, arg_32bit_rarbrc, arg_32bit_zarbrc, arg_32bit_rbrbrc) (arg_32bit_rarbu6, arg_32bit_zarbu6, arg_32bit_rbrbu6) (arg_32bit_rbrbs12, arg_32bit_ralimmrc, arg_32bit_rarblimm) (arg_32bit_zalimmrc, arg_32bit_zarblimm, arg_32bit_rbrblimm) (arg_32bit_ralimmu6, arg_32bit_zalimmu6, arg_32bit_zalimms12) (arg_32bit_ralimmlimm, arg_32bit_zalimmlimm, arg_32bit_rbrc) (arg_32bit_zarc, arg_32bit_rbu6, arg_32bit_zau6, arg_32bit_rblimm) (arg_32bit_zalimm, arg_32bit_limmrc, arg_32bit_limmu6) (arg_32bit_limms12, arg_32bit_limmlimm): Likewise. (arc_opcode arc_opcodes): Null terminate the array. (arc_num_opcodes): Remove. * arc-ext.h (INSERT_XOP): Define. (extInstruction_t): Likewise. (arcExtMap_instName): Delete. (arcExtMap_insn): New function. (arcExtMap_genOpcode): Likewise. * arc-ext.c (ExtInstruction): Remove. (create_map): Zero initialize instruction fields. (arcExtMap_instName): Remove. (arcExtMap_insn): New function. (dump_ARC_extmap): More info while debuging. (arcExtMap_genOpcode): New function. * arc-dis.c (find_format): New function. (print_insn_arc): Use find_format. (arc_get_disassembler): Enable dump_ARC_extmap only when debugging. Signed-off-by: Claudiu Zissulescu <claziss@synopsys.com>
This commit is contained in:
parent
37ab977937
commit
b99747aeed
|
@ -1,3 +1,28 @@
|
|||
2016-04-12 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* testsuite/gas/arc/textinsn-errors.d: New File.
|
||||
* testsuite/gas/arc/textinsn-errors.err: Likewise.
|
||||
* testsuite/gas/arc/textinsn-errors.s: Likewise.
|
||||
* testsuite/gas/arc/textinsn2op.d: Likewise.
|
||||
* testsuite/gas/arc/textinsn2op.s: Likewise.
|
||||
* testsuite/gas/arc/textinsn2op01.d: Likewise.
|
||||
* testsuite/gas/arc/textinsn2op01.s: Likewise.
|
||||
* testsuite/gas/arc/textinsn3op.d: Likewise.
|
||||
* testsuite/gas/arc/textinsn3op.s: Likewise.
|
||||
* doc/c-arc.texi (ARC Directives): Add .extInstruction
|
||||
documentation.
|
||||
* config/tc-arc.c (arcext_section): New variable.
|
||||
(arc_extinsn): New function.
|
||||
(md_pseudo_table): Add .extInstruction pseudo op.
|
||||
(attributes_t): New type.
|
||||
(suffixclass, syntaxclass, syntaxclassmod): New constant
|
||||
structures.
|
||||
(find_opcode_match): Remove arc_num_opcodes.
|
||||
(md_begin): Likewise.
|
||||
(tokenize_extinsn): New function.
|
||||
(arc_set_ext_seg): Likewise.
|
||||
(create_extinst_section): Likewise.
|
||||
|
||||
2016-04-12 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* config/tc-arc.c (preprocess_operands): Mark AUX symbol.
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "opcode/arc.h"
|
||||
#include "elf/arc.h"
|
||||
#include "../opcodes/arc-ext.h"
|
||||
|
||||
/* Defines section. */
|
||||
|
||||
|
@ -126,6 +127,9 @@ extern int target_big_endian;
|
|||
const char *arc_target_format = DEFAULT_TARGET_FORMAT;
|
||||
static int byte_order = DEFAULT_BYTE_ORDER;
|
||||
|
||||
/* Arc extension section. */
|
||||
static segT arcext_section;
|
||||
|
||||
/* By default relaxation is disabled. */
|
||||
static int relaxation_state = 0;
|
||||
|
||||
|
@ -135,7 +139,7 @@ extern int arc_get_mach (char *);
|
|||
static void arc_lcomm (int);
|
||||
static void arc_option (int);
|
||||
static void arc_extra_reloc (int);
|
||||
|
||||
static void arc_extinsn (int);
|
||||
|
||||
const pseudo_typeS md_pseudo_table[] =
|
||||
{
|
||||
|
@ -147,6 +151,8 @@ const pseudo_typeS md_pseudo_table[] =
|
|||
{ "lcommon", arc_lcomm, 0 },
|
||||
{ "cpu", arc_option, 0 },
|
||||
|
||||
{ "extinstruction", arc_extinsn, 0 },
|
||||
|
||||
{ "tls_gd_ld", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
|
||||
{ "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
|
||||
|
||||
|
@ -308,6 +314,35 @@ static struct arc_last_insn
|
|||
bfd_boolean has_delay_slot;
|
||||
} arc_last_insns[2];
|
||||
|
||||
/* Extension instruction suffix classes. */
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
int len;
|
||||
int class;
|
||||
} attributes_t;
|
||||
|
||||
static const attributes_t suffixclass[] =
|
||||
{
|
||||
{ "SUFFIX_FLAG", 11, ARC_SUFFIX_FLAG },
|
||||
{ "SUFFIX_COND", 11, ARC_SUFFIX_COND },
|
||||
{ "SUFFIX_NONE", 11, ARC_SUFFIX_NONE }
|
||||
};
|
||||
|
||||
/* Extension instruction syntax classes. */
|
||||
static const attributes_t syntaxclass[] =
|
||||
{
|
||||
{ "SYNTAX_3OP", 10, ARC_SYNTAX_3OP },
|
||||
{ "SYNTAX_2OP", 10, ARC_SYNTAX_2OP }
|
||||
};
|
||||
|
||||
/* Extension instruction syntax classes modifiers. */
|
||||
static const attributes_t syntaxclassmod[] =
|
||||
{
|
||||
{ "OP1_IMM_IMPLIED" , 15, ARC_OP1_IMM_IMPLIED },
|
||||
{ "OP1_MUST_BE_IMM" , 15, ARC_OP1_MUST_BE_IMM }
|
||||
};
|
||||
|
||||
/* Structure to hold an entry in ARC_OPCODE_HASH. */
|
||||
struct arc_opcode_hash_entry
|
||||
{
|
||||
|
@ -615,8 +650,8 @@ arc_opcode_hash_entry_iterator_next (const struct arc_opcode_hash_entry *entry,
|
|||
const char *old_name = iter->opcode->name;
|
||||
|
||||
iter->opcode++;
|
||||
if ((iter->opcode - arc_opcodes >= (int) arc_num_opcodes)
|
||||
|| (strcmp (old_name, iter->opcode->name) != 0))
|
||||
if (iter->opcode->name
|
||||
&& (strcmp (old_name, iter->opcode->name) != 0))
|
||||
{
|
||||
iter->index++;
|
||||
if (iter->index == entry->count)
|
||||
|
@ -629,6 +664,40 @@ arc_opcode_hash_entry_iterator_next (const struct arc_opcode_hash_entry *entry,
|
|||
return iter->opcode;
|
||||
}
|
||||
|
||||
/* Insert an opcode into opcode hash structure. */
|
||||
|
||||
static void
|
||||
arc_insert_opcode (const struct arc_opcode *opcode)
|
||||
{
|
||||
const char *name, *retval;
|
||||
struct arc_opcode_hash_entry *entry;
|
||||
name = opcode->name;
|
||||
|
||||
entry = hash_find (arc_opcode_hash, name);
|
||||
if (entry == NULL)
|
||||
{
|
||||
entry = xmalloc (sizeof (*entry));
|
||||
entry->count = 0;
|
||||
entry->opcode = NULL;
|
||||
|
||||
retval = hash_insert (arc_opcode_hash, name, (void *) entry);
|
||||
if (retval)
|
||||
as_fatal (_("internal error: can't hash opcode '%s': %s"),
|
||||
name, retval);
|
||||
}
|
||||
|
||||
entry->opcode = xrealloc (entry->opcode,
|
||||
sizeof (const struct arc_opcode *)
|
||||
* (entry->count + 1));
|
||||
|
||||
if (entry->opcode == NULL)
|
||||
as_fatal (_("Virtual memory exhausted"));
|
||||
|
||||
entry->opcode[entry->count] = opcode;
|
||||
entry->count++;
|
||||
}
|
||||
|
||||
|
||||
/* Like md_number_to_chars but used for limms. The 4-byte limm value,
|
||||
is encoded as 'middle-endian' for a little-endian target. FIXME!
|
||||
this function is used for regular 4 byte instructions as well. */
|
||||
|
@ -1611,7 +1680,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
|
|||
from BKTOK. */
|
||||
tok[tokidx].X_op = O_constant;
|
||||
tok[tokidx].X_add_number = auxr->address;
|
||||
ARC_SET_FLAG (tok[i].X_add_symbol, ARC_FLAG_AUX);
|
||||
ARC_SET_FLAG (tok[tokidx].X_add_symbol, ARC_FLAG_AUX);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2218,7 +2287,7 @@ declare_register_set (void)
|
|||
void
|
||||
md_begin (void)
|
||||
{
|
||||
unsigned int i;
|
||||
const struct arc_opcode *opcode = arc_opcodes;
|
||||
|
||||
if (!mach_type_specified_p)
|
||||
arc_select_cpu ("arc700");
|
||||
|
@ -2238,37 +2307,17 @@ md_begin (void)
|
|||
as_fatal (_("Virtual memory exhausted"));
|
||||
|
||||
/* Initialize the hash table with the insns. */
|
||||
for (i = 0; i < arc_num_opcodes;)
|
||||
do
|
||||
{
|
||||
const char *name, *retval;
|
||||
struct arc_opcode_hash_entry *entry;
|
||||
const char *name = opcode->name;
|
||||
|
||||
name = arc_opcodes[i].name;
|
||||
arc_insert_opcode (opcode);
|
||||
|
||||
entry = hash_find (arc_opcode_hash, name);
|
||||
if (entry == NULL)
|
||||
{
|
||||
entry = xmalloc (sizeof (*entry));
|
||||
entry->count = 0;
|
||||
entry->opcode = NULL;
|
||||
|
||||
retval = hash_insert (arc_opcode_hash, name, (void *) entry);
|
||||
if (retval)
|
||||
as_fatal (_("internal error: can't hash opcode '%s': %s"),
|
||||
name, retval);
|
||||
}
|
||||
|
||||
entry->opcode = xrealloc (entry->opcode,
|
||||
sizeof (const struct arc_opcode *)
|
||||
* entry->count + 1);
|
||||
entry->opcode [entry->count] = &arc_opcodes[i];
|
||||
entry->count++;
|
||||
|
||||
while (++i < arc_num_opcodes
|
||||
&& (arc_opcodes[i].name == name
|
||||
|| !strcmp (arc_opcodes[i].name, name)))
|
||||
while (++opcode && opcode->name
|
||||
&& (opcode->name == name
|
||||
|| !strcmp (opcode->name, name)))
|
||||
continue;
|
||||
}
|
||||
}while (opcode->name);
|
||||
|
||||
/* Register declaration. */
|
||||
arc_reg_hash = hash_new ();
|
||||
|
@ -3877,3 +3926,275 @@ arc_adjust_symtab (void)
|
|||
/* Now do generic ELF adjustments. */
|
||||
elf_adjust_symtab ();
|
||||
}
|
||||
|
||||
static void
|
||||
tokenize_extinsn (extInstruction_t *einsn)
|
||||
{
|
||||
char *p, c;
|
||||
char *insn_name;
|
||||
unsigned char major_opcode;
|
||||
unsigned char sub_opcode;
|
||||
unsigned char syntax_class = 0;
|
||||
unsigned char syntax_class_modifiers = 0;
|
||||
unsigned char suffix_class = 0;
|
||||
unsigned int i;
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
/* 1st: get instruction name. */
|
||||
p = input_line_pointer;
|
||||
c = get_symbol_name (&p);
|
||||
|
||||
insn_name = xstrdup (p);
|
||||
restore_line_pointer (c);
|
||||
|
||||
/* 2nd: get major opcode. */
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
as_bad (_("expected comma after instruction name"));
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
input_line_pointer++;
|
||||
major_opcode = get_absolute_expression ();
|
||||
|
||||
/* 3rd: get sub-opcode. */
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
as_bad (_("expected comma after major opcode"));
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
input_line_pointer++;
|
||||
sub_opcode = get_absolute_expression ();
|
||||
|
||||
/* 4th: get suffix class. */
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
as_bad ("expected comma after sub opcode");
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
input_line_pointer++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (suffixclass); i++)
|
||||
{
|
||||
if (!strncmp (suffixclass[i].name, input_line_pointer,
|
||||
suffixclass[i].len))
|
||||
{
|
||||
suffix_class |= suffixclass[i].class;
|
||||
input_line_pointer += suffixclass[i].len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE (suffixclass))
|
||||
{
|
||||
as_bad ("invalid suffix class");
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
if (*input_line_pointer == '|')
|
||||
input_line_pointer++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* 5th: get syntax class and syntax class modifiers. */
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
as_bad ("expected comma after suffix class");
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
input_line_pointer++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (syntaxclassmod); i++)
|
||||
{
|
||||
if (!strncmp (syntaxclassmod[i].name,
|
||||
input_line_pointer,
|
||||
syntaxclassmod[i].len))
|
||||
{
|
||||
syntax_class_modifiers |= syntaxclassmod[i].class;
|
||||
input_line_pointer += syntaxclassmod[i].len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE (syntaxclassmod))
|
||||
{
|
||||
for (i = 0; i < ARRAY_SIZE (syntaxclass); i++)
|
||||
{
|
||||
if (!strncmp (syntaxclass[i].name,
|
||||
input_line_pointer,
|
||||
syntaxclass[i].len))
|
||||
{
|
||||
syntax_class |= syntaxclass[i].class;
|
||||
input_line_pointer += syntaxclass[i].len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE (syntaxclass))
|
||||
{
|
||||
as_bad ("missing syntax class");
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
if (*input_line_pointer == '|')
|
||||
input_line_pointer++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
|
||||
einsn->name = insn_name;
|
||||
einsn->major = major_opcode;
|
||||
einsn->minor = sub_opcode;
|
||||
einsn->syntax = syntax_class;
|
||||
einsn->modsyn = syntax_class_modifiers;
|
||||
einsn->suffix = suffix_class;
|
||||
einsn->flags = syntax_class
|
||||
| (syntax_class_modifiers & ARC_OP1_IMM_IMPLIED ? 0x10 : 0);
|
||||
}
|
||||
|
||||
/* Generate an extension section. */
|
||||
|
||||
static int
|
||||
arc_set_ext_seg (void)
|
||||
{
|
||||
if (!arcext_section)
|
||||
{
|
||||
arcext_section = subseg_new (".arcextmap", 0);
|
||||
bfd_set_section_flags (stdoutput, arcext_section,
|
||||
SEC_READONLY | SEC_HAS_CONTENTS);
|
||||
}
|
||||
else
|
||||
subseg_set (arcext_section, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create an extension instruction 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.
|
||||
|
||||
[2]: Major opcode.
|
||||
[3]: Sub-opcode.
|
||||
[4]: Syntax (flags).
|
||||
[5]+ Name instruction.
|
||||
|
||||
The sequence is terminated by an empty entry. */
|
||||
|
||||
static void
|
||||
create_extinst_section (extInstruction_t *einsn)
|
||||
{
|
||||
|
||||
segT old_sec = now_seg;
|
||||
int old_subsec = now_subseg;
|
||||
char *p;
|
||||
int name_len = strlen (einsn->name);
|
||||
|
||||
arc_set_ext_seg ();
|
||||
|
||||
p = frag_more (1);
|
||||
*p = 5 + name_len + 1;
|
||||
p = frag_more (1);
|
||||
*p = EXT_INSTRUCTION;
|
||||
p = frag_more (1);
|
||||
*p = einsn->major;
|
||||
p = frag_more (1);
|
||||
*p = einsn->minor;
|
||||
p = frag_more (1);
|
||||
*p = einsn->flags;
|
||||
p = frag_more (name_len + 1);
|
||||
strcpy (p, einsn->name);
|
||||
|
||||
subseg_set (old_sec, old_subsec);
|
||||
}
|
||||
|
||||
/* Handler .extinstruction pseudo-op. */
|
||||
|
||||
static void
|
||||
arc_extinsn (int ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
extInstruction_t einsn;
|
||||
struct arc_opcode *arc_ext_opcodes;
|
||||
const char *errmsg = NULL;
|
||||
unsigned char moplow, mophigh;
|
||||
|
||||
memset (&einsn, 0, sizeof (einsn));
|
||||
tokenize_extinsn (&einsn);
|
||||
|
||||
/* Check if the name is already used. */
|
||||
if (arc_find_opcode (einsn.name))
|
||||
as_warn (_("Pseudocode already used %s"), einsn.name);
|
||||
|
||||
/* Check the opcode ranges. */
|
||||
moplow = 0x05;
|
||||
mophigh = (arc_target & (ARC_OPCODE_ARCv2EM
|
||||
| ARC_OPCODE_ARCv2HS)) ? 0x07 : 0x0a;
|
||||
|
||||
if ((einsn.major > mophigh) || (einsn.major < moplow))
|
||||
as_fatal (_("major opcode not in range [0x%02x - 0x%02x]"), moplow, mophigh);
|
||||
|
||||
if ((einsn.minor > 0x3f) && (einsn.major != 0x0a)
|
||||
&& (einsn.major != 5) && (einsn.major != 9))
|
||||
as_fatal (_("minor opcode not in range [0x00 - 0x3f]"));
|
||||
|
||||
switch (einsn.syntax & (ARC_SYNTAX_3OP | ARC_SYNTAX_2OP))
|
||||
{
|
||||
case ARC_SYNTAX_3OP:
|
||||
if (einsn.modsyn & ARC_OP1_IMM_IMPLIED)
|
||||
as_fatal (_("Improper use of OP1_IMM_IMPLIED"));
|
||||
break;
|
||||
case ARC_SYNTAX_2OP:
|
||||
if (einsn.modsyn & ARC_OP1_MUST_BE_IMM)
|
||||
as_fatal (_("Improper use of OP1_MUST_BE_IMM"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
arc_ext_opcodes = arcExtMap_genOpcode (&einsn, arc_target, &errmsg);
|
||||
if (arc_ext_opcodes == NULL)
|
||||
{
|
||||
if (errmsg)
|
||||
as_fatal ("%s", errmsg);
|
||||
else
|
||||
as_fatal (_("Couldn't generate extension instruction opcodes"));
|
||||
}
|
||||
else if (errmsg)
|
||||
as_warn ("%s", errmsg);
|
||||
|
||||
/* Insert the extension instruction. */
|
||||
arc_insert_opcode ((const struct arc_opcode *) arc_ext_opcodes);
|
||||
|
||||
create_extinst_section (&einsn);
|
||||
}
|
||||
|
||||
/* Local variables:
|
||||
eval: (c-set-style "gnu")
|
||||
indent-tabs-mode: t
|
||||
End: */
|
||||
|
|
|
@ -320,7 +320,7 @@ machine directives:
|
|||
@table @code
|
||||
|
||||
@cindex @code{lcomm} directive
|
||||
@item .lcomm @var{symbol} , @var{length}[, @var{alignment}]
|
||||
@item .lcomm @var{symbol}, @var{length}[, @var{alignment}]
|
||||
Reserve @var{length} (an absolute expression) bytes for a local common
|
||||
denoted by @var{symbol}. The section and value of @var{symbol} are
|
||||
those of the new local common. The addresses are allocated in the bss
|
||||
|
@ -336,11 +336,11 @@ largest power of two less than or equal to the size of the symbol, up
|
|||
to a maximum of 16.
|
||||
|
||||
@cindex @code{lcommon} directive
|
||||
@item .lcommon @var{symbol} , @var{length}[, @var{alignment}]
|
||||
@item .lcommon @var{symbol}, @var{length}[, @var{alignment}]
|
||||
The same as @code{lcomm} directive.
|
||||
|
||||
@cindex @code{cpu} directive, ARC
|
||||
@cindex @code{cpu} directive, ARC
|
||||
@cindex @code{cpu} directive
|
||||
@item .cpu @var{cpu}
|
||||
The @code{.cpu} directive must be followed by the desired core
|
||||
version. Permitted values for CPU are:
|
||||
@table @code
|
||||
|
@ -361,6 +361,93 @@ Assemble for the ARC HS instruction set.
|
|||
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 .extInstruction @var{name}, @var{opcode}, @var{subopcode}, @var{suffixclass}, @var{syntaxclass}
|
||||
@cindex @code{extInstruction} directive
|
||||
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
|
||||
user.
|
||||
|
||||
The first argument, @var{name}, gives the name of the instruction.
|
||||
|
||||
The second argument, @var{opcode}, is the opcode to be used (bits 31:27
|
||||
in the encoding).
|
||||
|
||||
The third argument, @var{subopcode}, is the sub-opcode to be used, but
|
||||
the correct value also depends on the fifth argument,
|
||||
@var{syntaxclass}
|
||||
|
||||
The fourth argument, @var{suffixclass}, determines the kinds of
|
||||
suffixes to be allowed. Valid values are:
|
||||
@table @code
|
||||
@item SUFFIX_NONE
|
||||
No suffixes are permitted;
|
||||
|
||||
@item SUFFIX_COND
|
||||
Conditional suffixes are permitted;
|
||||
|
||||
@item SUFFIX_FLAG
|
||||
Flag setting suffixes are permitted.
|
||||
|
||||
@item SUFFIX_COND|SUFFIX_FLAG
|
||||
Both conditional and flag setting suffices are permitted.
|
||||
|
||||
@end table
|
||||
|
||||
The fifth and final argument, @var{syntaxclass}, determines the syntax
|
||||
class for the instruction. It can have the following values:
|
||||
@table @code
|
||||
@item SYNTAX_2OP
|
||||
Two Operand Instruction;
|
||||
|
||||
@item SYNTAX_3OP
|
||||
Three Operand Instruction.
|
||||
@end table
|
||||
|
||||
The syntax class may be followed by @samp{|} and one of the following
|
||||
modifiers.
|
||||
@table @code
|
||||
|
||||
@item OP1_MUST_BE_IMM
|
||||
Modifies syntax class @code{SYNTAX_3OP}, specifying that the first
|
||||
operand of a three-operand instruction must be an immediate (i.e., the
|
||||
result is discarded). This is usually used to set the flags using
|
||||
specific instructions and not retain results.
|
||||
|
||||
@item OP1_IMM_IMPLIED
|
||||
Modifies syntax class @code{SYNTAX_20P}, specifying that there is an
|
||||
implied immediate destination operand which does not appear in the
|
||||
syntax.
|
||||
|
||||
For example, if the source code contains an instruction like:
|
||||
@example
|
||||
inst r1,r2
|
||||
@end example
|
||||
the first argument is an implied immediate (that is, the result is
|
||||
discarded). This is the same as though the source code were: inst
|
||||
0,r1,r2.
|
||||
|
||||
@end table
|
||||
|
||||
For example, defining a 64-bit multiplier with immediate operands:
|
||||
@example
|
||||
.extInstruction mp64, 0x07, 0x2d, SUFFIX_COND|SUFFIX_FLAG,
|
||||
SYNTAX_3OP|OP1_MUST_BE_IMM
|
||||
@end example
|
||||
which specifies an extension instruction named @code{mp64} with 3
|
||||
operands. It sets the flags and can be used with a condition code,
|
||||
for which the first operand is an immediate, i.e. equivalent to
|
||||
discarding the result of the operation.
|
||||
|
||||
A two operands instruction variant would be:
|
||||
@example
|
||||
.extInstruction mul64, 0x07, 0x2d, SUFFIX_COND,
|
||||
SYNTAX_2OP|OP1_IMM_IMPLIED
|
||||
@end example
|
||||
which describes a two operand instruction with an implicit first
|
||||
immediate operand. The result of this operation would be discarded.
|
||||
|
||||
@end table
|
||||
|
||||
@node ARC Modifiers
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#error-output: textinsn-errors.err
|
|
@ -0,0 +1,2 @@
|
|||
[^:]*: Assembler messages:
|
||||
[^:]*:1: Warning: Suffix SUFFIX_COND ignored
|
|
@ -0,0 +1 @@
|
|||
.extInstruction myinsn0, 0x07, 0x2d, SUFFIX_FLAG|SUFFIX_COND, SYNTAX_2OP
|
|
@ -0,0 +1,24 @@
|
|||
#objdump: -dr
|
||||
|
||||
.*: +file format .*arc.*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
[0-9a-f]+ <.text>:
|
||||
0: 382f 006d myinsn r0,r1
|
||||
4: 3b2f 372d myinsn fp,sp
|
||||
8: 386f 002d myinsn r0,0
|
||||
c: 392f 0fad ffff ffff myinsn r1,0xffffffff
|
||||
14: 3e2f 70ad myinsn 0,r2
|
||||
18: 3c2f 0fad 0000 00ff myinsn r4,0xff
|
||||
20: 3e2f 0fad ffff ff00 myinsn r6,0xffffff00
|
||||
28: 382f 1fad 0000 0100 myinsn r8,0x100
|
||||
30: 392f 1fad ffff feff myinsn r9,0xfffffeff
|
||||
38: 3b2f 1fad 4242 4242 myinsn r11,0x42424242
|
||||
40: 382f 0fad 0000 0000 myinsn r0,0
|
||||
44: R_ARC_32_ME foo
|
||||
48: 382f 806d myinsn.f r0,r1
|
||||
4c: 3a6f 806d myinsn.f r2,0x1
|
||||
50: 3e2f f12d myinsn.f 0,r4
|
||||
54: 3d2f 8fad 0000 0200 myinsn.f r5,0x200
|
|
@ -0,0 +1,22 @@
|
|||
# Insn 3 .extInstruction test
|
||||
.extInstruction myinsn, 0x07, 0x2d, SUFFIX_FLAG, SYNTAX_2OP
|
||||
|
||||
myinsn r0,r1
|
||||
myinsn fp,sp
|
||||
|
||||
myinsn r0,0
|
||||
myinsn r1,-1
|
||||
myinsn 0,r2
|
||||
myinsn r4,255
|
||||
myinsn r6,-256
|
||||
|
||||
myinsn r8,256
|
||||
myinsn r9,-257
|
||||
myinsn r11,0x42424242
|
||||
|
||||
myinsn r0,foo
|
||||
|
||||
myinsn.f r0,r1
|
||||
myinsn.f r2,1
|
||||
myinsn.f 0,r4
|
||||
myinsn.f r5,512
|
|
@ -0,0 +1,27 @@
|
|||
#objdump: -dr
|
||||
|
||||
.*: +file format .*arc.*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
[0-9a-f]+ <.text>:
|
||||
0: 382d 007e myinsn r0,r1
|
||||
4: 3b2d 373e myinsn fp,sp
|
||||
8: 386d 003e myinsn r0,0
|
||||
c: 392d 0fbe ffff ffff myinsn r1,0xffffffff
|
||||
14: 3eed 7080 0000 0000 myinsn 0,r2
|
||||
1c: 3c2d 0fbe 0000 00ff myinsn r4,0xff
|
||||
24: 3e2d 0fbe ffff ff00 myinsn r6,0xffffff00
|
||||
2c: 382d 1fbe 0000 0100 myinsn r8,0x100
|
||||
34: 392d 1fbe ffff feff myinsn r9,0xfffffeff
|
||||
3c: 3b2d 1fbe 4242 4242 myinsn r11,0x42424242
|
||||
44: 382d 0fbe 0000 0000 myinsn r0,0
|
||||
48: R_ARC_32_ME foo
|
||||
4c: 382d 807e myinsn.f r0,r1
|
||||
50: 3a6d 807e myinsn.f r2,0x1
|
||||
54: 3eed f100 0000 0000 myinsn.f 0,r4
|
||||
5c: 3d2d 8fbe 0000 0200 myinsn.f r5,0x200
|
||||
64: 3eed f102 0000 0000 myinsn.ne.f 0,r4
|
||||
6c: 3eed ff85 dead beef myinsn.c.f 0xdeadbeef,0xdeadbeef
|
||||
74: 3eed f0a6 dead beef myinsn.nc.f 0xdeadbeef,0x2
|
|
@ -0,0 +1,26 @@
|
|||
# Insn 2op .extInstruction test
|
||||
.extInstruction myinsn, 0x07, 0x2d, SUFFIX_FLAG|SUFFIX_COND, SYNTAX_2OP|OP1_IMM_IMPLIED
|
||||
|
||||
myinsn r0,r1
|
||||
myinsn fp,sp
|
||||
|
||||
myinsn r0,0
|
||||
myinsn r1,-1
|
||||
myinsn 0,r2
|
||||
myinsn r4,255
|
||||
myinsn r6,-256
|
||||
|
||||
myinsn r8,256
|
||||
myinsn r9,-257
|
||||
myinsn r11,0x42424242
|
||||
|
||||
myinsn r0,foo
|
||||
|
||||
myinsn.f r0,r1
|
||||
myinsn.f r2,1
|
||||
myinsn.f 0,r4
|
||||
myinsn.f r5,512
|
||||
|
||||
myinsn.ne.f 0,r4
|
||||
myinsn.c.f 0xdeadbeef, 0xdeadbeef
|
||||
myinsn.nc.f 0xdeadbeef, 0x02
|
|
@ -0,0 +1,63 @@
|
|||
#objdump: -dr
|
||||
|
||||
.*: +file format .*arc.*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
[0-9a-f]+ <.text>:
|
||||
0: 392d 0080 myinsn r0,r1,r2
|
||||
4: 3b2d 371a myinsn gp,fp,sp
|
||||
8: 3e2d 37dd myinsn ilink,r30,blink
|
||||
c: 396d 0000 myinsn r0,r1,0
|
||||
10: 3e2d 7080 0000 0000 myinsn r0,0,r2
|
||||
18: 392d 00be myinsn 0,r1,r2
|
||||
1c: 392d 0f80 ffff ffff myinsn r0,r1,0xffffffff
|
||||
24: 3e2d 7080 ffff ffff myinsn r0,0xffffffff,r2
|
||||
2c: 392d 0f80 0000 00ff myinsn r0,r1,0xff
|
||||
34: 3e2d 7080 0000 00ff myinsn r0,0xff,r2
|
||||
3c: 392d 0f80 ffff ff00 myinsn r0,r1,0xffffff00
|
||||
44: 3e2d 7080 ffff ff00 myinsn r0,0xffffff00,r2
|
||||
4c: 392d 0f80 0000 0100 myinsn r0,r1,0x100
|
||||
54: 3e2d 7080 ffff feff myinsn r0,0xfffffeff,r2
|
||||
5c: 3e2d 7f80 0000 0100 myinsn r0,0x100,0x100
|
||||
64: 392d 0f80 0000 0000 myinsn r0,r1,0
|
||||
68: R_ARC_32_ME foo
|
||||
6c: 38ed 0080 myinsn r0,r0,r2
|
||||
70: 3bed 0140 myinsn r3,r3,r5
|
||||
74: 3eed 0201 myinsn.eq r6,r6,r8
|
||||
78: 39ed 12c1 myinsn.eq r9,r9,r11
|
||||
7c: 3ced 1382 myinsn.ne r12,r12,r14
|
||||
80: 3fed 1442 myinsn.ne r15,r15,r17
|
||||
84: 3aed 2503 myinsn.p r18,r18,r20
|
||||
88: 3ded 25c3 myinsn.p r21,r21,r23
|
||||
8c: 38ed 3684 myinsn.n r24,r24,gp
|
||||
90: 3bed 3744 myinsn.n fp,fp,ilink
|
||||
94: 3eed 37c5 myinsn.c r30,r30,blink
|
||||
98: 3bed 00c5 myinsn.c r3,r3,r3
|
||||
9c: 3bed 0205 myinsn.c r3,r3,r8
|
||||
a0: 3bed 0106 myinsn.nc r3,r3,r4
|
||||
a4: 3ced 0106 myinsn.nc r4,r4,r4
|
||||
a8: 3ced 01c6 myinsn.nc r4,r4,r7
|
||||
ac: 3ced 0147 myinsn.v r4,r4,r5
|
||||
b0: 3ded 0147 myinsn.v r5,r5,r5
|
||||
b4: 3ded 0148 myinsn.nv r5,r5,r5
|
||||
b8: 3ded 0148 myinsn.nv r5,r5,r5
|
||||
bc: 3eed 0009 myinsn.gt r6,r6,r0
|
||||
c0: 38ed 002a myinsn.ge r0,r0,0
|
||||
c4: 39ed 006b myinsn.lt r1,r1,0x1
|
||||
c8: 3bed 00ed myinsn.hi r3,r3,0x3
|
||||
cc: 3ced 012e myinsn.ls r4,r4,0x4
|
||||
d0: 3ded 016f myinsn.pnz r5,r5,0x5
|
||||
d4: 392d 8080 myinsn.f r0,r1,r2
|
||||
d8: 396d 8040 myinsn.f r0,r1,0x1
|
||||
dc: 3e2d f080 0000 0001 myinsn.f r0,0x1,r2
|
||||
e4: 392d 80be myinsn.f 0,r1,r2
|
||||
e8: 392d 8f80 0000 0200 myinsn.f r0,r1,0x200
|
||||
f0: 3e2d f080 0000 0200 myinsn.f r0,0x200,r2
|
||||
f8: 39ed 8081 myinsn.eq.f r1,r1,r2
|
||||
fc: 38ed 8022 myinsn.ne.f r0,r0,0
|
||||
100: 3aed 808b myinsn.lt.f r2,r2,r2
|
||||
104: 3eed f0a9 0000 0001 myinsn.gt.f 0,0x1,0x2
|
||||
10c: 3eed ff8c 0000 0200 myinsn.le.f 0,0x200,0x200
|
||||
114: 3eed f0aa 0000 0200 myinsn.ge.f 0,0x200,0x2
|
|
@ -0,0 +1,64 @@
|
|||
# Insn 3op .extInstruction test
|
||||
.extInstruction myinsn, 0x07, 0x2d, SUFFIX_FLAG|SUFFIX_COND, SYNTAX_3OP
|
||||
|
||||
myinsn r0,r1,r2
|
||||
myinsn r26,fp,sp
|
||||
myinsn ilink1,ilink2,blink
|
||||
|
||||
myinsn r0,r1,0
|
||||
myinsn r0,0,r2
|
||||
myinsn 0,r1,r2
|
||||
myinsn r0,r1,-1
|
||||
myinsn r0,-1,r2
|
||||
myinsn r0,r1,255
|
||||
myinsn r0,255,r2
|
||||
myinsn r0,r1,-256
|
||||
myinsn r0,-256,r2
|
||||
|
||||
myinsn r0,r1,256
|
||||
myinsn r0,-257,r2
|
||||
|
||||
myinsn r0,256,256
|
||||
|
||||
myinsn r0,r1,foo
|
||||
|
||||
myinsn.al r0,r0,r2
|
||||
myinsn.ra r3,r3,r5
|
||||
myinsn.eq r6,r6,r8
|
||||
myinsn.z r9,r9,r11
|
||||
myinsn.ne r12,r12,r14
|
||||
myinsn.nz r15,r15,r17
|
||||
myinsn.pl r18,r18,r20
|
||||
myinsn.p r21,r21,r23
|
||||
myinsn.mi r24,r24,r26
|
||||
myinsn.n r27,r27,r29
|
||||
myinsn.cs r30,r30,r31
|
||||
myinsn.c r3,r3,r3
|
||||
myinsn.lo r3,r3,r8
|
||||
myinsn.cc r3,r3,r4
|
||||
myinsn.nc r4,r4,r4
|
||||
myinsn.hs r4,r4,r7
|
||||
myinsn.vs r4,r4,r5
|
||||
myinsn.v r5,r5,r5
|
||||
myinsn.vc r5,r5,r5
|
||||
myinsn.nv r5,r5,r5
|
||||
myinsn.gt r6,r6,r0
|
||||
myinsn.ge r0,r0,0
|
||||
myinsn.lt r1,r1,1
|
||||
myinsn.hi r3,r3,3
|
||||
myinsn.ls r4,r4,4
|
||||
myinsn.pnz r5,r5,5
|
||||
|
||||
myinsn.f r0,r1,r2
|
||||
myinsn.f r0,r1,1
|
||||
myinsn.f r0,1,r2
|
||||
myinsn.f 0,r1,r2
|
||||
myinsn.f r0,r1,512
|
||||
myinsn.f r0,512,r2
|
||||
|
||||
myinsn.eq.f r1,r1,r2
|
||||
myinsn.ne.f r0,r0,0
|
||||
myinsn.lt.f r2,r2,r2
|
||||
myinsn.gt.f 0,1,2
|
||||
myinsn.le.f 0,512,512
|
||||
myinsn.ge.f 0,512,2
|
|
@ -1,30 +1,47 @@
|
|||
22016-04-05 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
2016-04-12 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* opcode/arc.h (DPA, DPX, SPX): New subclass enums.
|
||||
(ARC_FPUDA): Define.
|
||||
(arc_aux_reg): Add new field.
|
||||
* opcode/arc.h (arc_num_opcodes): Remove.
|
||||
(ARC_SYNTAX_3OP, ARC_SYNTAX_2OP, ARC_OP1_MUST_BE_IMM)
|
||||
(ARC_OP1_IMM_IMPLIED, ARC_SUFFIX_NONE, ARC_SUFFIX_COND)
|
||||
(ARC_SUFFIX_FLAG): Define.
|
||||
(flags_none, flags_f, flags_cc, flags_ccf): Declare.
|
||||
(arg_none, arg_32bit_rarbrc, arg_32bit_zarbrc, arg_32bit_rbrbrc)
|
||||
(arg_32bit_rarbu6, arg_32bit_zarbu6, arg_32bit_rbrbu6)
|
||||
(arg_32bit_rbrbs12, arg_32bit_ralimmrc, arg_32bit_rarblimm)
|
||||
(arg_32bit_zalimmrc, arg_32bit_zarblimm, arg_32bit_rbrblimm)
|
||||
(arg_32bit_ralimmu6, arg_32bit_zalimmu6, arg_32bit_zalimms12)
|
||||
(arg_32bit_ralimmlimm, arg_32bit_zalimmlimm, arg_32bit_rbrc)
|
||||
(arg_32bit_zarc, arg_32bit_rbu6, arg_32bit_zau6, arg_32bit_rblimm)
|
||||
(arg_32bit_zalimm, arg_32bit_limmrc, arg_32bit_limmu6)
|
||||
(arg_32bit_limms12, arg_32bit_limmlimm): Likewise.
|
||||
|
||||
016-04-05 Cupertino Miranda <cmiranda@synopsys.com>
|
||||
2016-04-05 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* opcode/arc.h (DPA, DPX, SPX): New subclass enums.
|
||||
(ARC_FPUDA): Define.
|
||||
(arc_aux_reg): Add new field.
|
||||
|
||||
2016-04-05 Cupertino Miranda <cmiranda@synopsys.com>
|
||||
|
||||
* opcode/arc-func.h (replace_bits24): Changed.
|
||||
(replace_bits24_be): Created.
|
||||
|
||||
2016-03-29 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* opcode/arc.h (insn_subclass_t): Add QUARKSE subclass.
|
||||
(FIELDA, FIELDB, FIELDC, FIELDF, FIELDQ, INSN3OP, INSN2OP)
|
||||
(INSN2OP, INSN3OP_ABC, INSN3OP_ALC, INSN3OP_ABL, INSN3OP_ALL)
|
||||
(INSN3OP_0BC, INSN3OP_0LC, INSN3OP_0BL, INSN3OP_0LL, INSN3OP_ABU)
|
||||
(INSN3OP_ALU, INSN3OP_0BU, INSN3OP_0LU, INSN3OP_BBS, INSN3OP_0LS)
|
||||
(INSN3OP_CBBC, INSN3OP_CBBL, INSN3OP_C0LC, INSN3OP_C0LL)
|
||||
(INSN3OP_CBBU, INSN3OP_C0LU, MINSN3OP_ABC, MINSN3OP_ALC)
|
||||
(MINSN3OP_ABL, MINSN3OP_ALL, MINSN3OP_0BC, MINSN3OP_0LC)
|
||||
(MINSN3OP_0BL, MINSN3OP_0LL, MINSN3OP_ABU, MINSN3OP_ALU)
|
||||
(MINSN3OP_0BU, MINSN3OP_0LU, MINSN3OP_BBS, MINSN3OP_0LS)
|
||||
(MINSN3OP_CBBC, MINSN3OP_CBBL, MINSN3OP_C0LC, MINSN3OP_C0LL)
|
||||
(MINSN3OP_CBBU, MINSN3OP_C0LU, INSN2OP_BC, INSN2OP_BL, INSN2OP_0C)
|
||||
(INSN2OP_0L INSN2OP_BU, INSN2OP_0U, MINSN2OP_BC, MINSN2OP_BL)
|
||||
(MINSN2OP_0C, MINSN2OP_0L, MINSN2OP_BU, MINSN2OP_0U): Define.
|
||||
* opcode/arc.h (insn_subclass_t): Add QUARKSE subclass.
|
||||
(FIELDA, FIELDB, FIELDC, FIELDF, FIELDQ, INSN3OP, INSN2OP)
|
||||
(INSN2OP, INSN3OP_ABC, INSN3OP_ALC, INSN3OP_ABL, INSN3OP_ALL)
|
||||
(INSN3OP_0BC, INSN3OP_0LC, INSN3OP_0BL, INSN3OP_0LL, INSN3OP_ABU)
|
||||
(INSN3OP_ALU, INSN3OP_0BU, INSN3OP_0LU, INSN3OP_BBS, INSN3OP_0LS)
|
||||
(INSN3OP_CBBC, INSN3OP_CBBL, INSN3OP_C0LC, INSN3OP_C0LL)
|
||||
(INSN3OP_CBBU, INSN3OP_C0LU, MINSN3OP_ABC, MINSN3OP_ALC)
|
||||
(MINSN3OP_ABL, MINSN3OP_ALL, MINSN3OP_0BC, MINSN3OP_0LC)
|
||||
(MINSN3OP_0BL, MINSN3OP_0LL, MINSN3OP_ABU, MINSN3OP_ALU)
|
||||
(MINSN3OP_0BU, MINSN3OP_0LU, MINSN3OP_BBS, MINSN3OP_0LS)
|
||||
(MINSN3OP_CBBC, MINSN3OP_CBBL, MINSN3OP_C0LC, MINSN3OP_C0LL)
|
||||
(MINSN3OP_CBBU, MINSN3OP_C0LU, INSN2OP_BC, INSN2OP_BL, INSN2OP_0C)
|
||||
(INSN2OP_0L INSN2OP_BU, INSN2OP_0U, MINSN2OP_BC, MINSN2OP_BL)
|
||||
(MINSN2OP_0C, MINSN2OP_0L, MINSN2OP_BU, MINSN2OP_0U): Define.
|
||||
|
||||
2016-03-22 Trevor Saunders <tbsaunde+binutils@tbsaunde.org>
|
||||
|
||||
|
@ -124,8 +141,8 @@
|
|||
2016-02-10 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
Janek van Oirschot <jvanoirs@synopsys.com>
|
||||
|
||||
* opcode/arc.h (arc_opcode arc_relax_opcodes, arc_num_relax_opcodes):
|
||||
Declare.
|
||||
* opcode/arc.h (arc_opcode arc_relax_opcodes)
|
||||
(arc_num_relax_opcodes): Declare.
|
||||
|
||||
2016-02-09 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
|
|
|
@ -130,7 +130,6 @@ struct arc_opcode
|
|||
in the order in which the disassembler should consider
|
||||
instructions. */
|
||||
extern const struct arc_opcode arc_opcodes[];
|
||||
extern const unsigned arc_num_opcodes;
|
||||
|
||||
/* CPU Availability. */
|
||||
#define ARC_OPCODE_ARC600 0x0001 /* ARC 600 specific insns. */
|
||||
|
@ -494,4 +493,54 @@ extern const unsigned arc_num_relax_opcodes;
|
|||
#define MINSN2OP_BU (~(FIELDF | FIELDB (63) | FIELDC (63)))
|
||||
#define MINSN2OP_0U (~(FIELDF | FIELDC (63)))
|
||||
|
||||
/* Various constants used when defining an extension instruction. */
|
||||
#define ARC_SYNTAX_3OP (1 << 0)
|
||||
#define ARC_SYNTAX_2OP (1 << 1)
|
||||
#define ARC_OP1_MUST_BE_IMM (1 << 2)
|
||||
#define ARC_OP1_IMM_IMPLIED (1 << 3)
|
||||
|
||||
#define ARC_SUFFIX_NONE (1 << 0)
|
||||
#define ARC_SUFFIX_COND (1 << 1)
|
||||
#define ARC_SUFFIX_FLAG (1 << 2)
|
||||
|
||||
|
||||
/* Constants needed to initialize extension instructions. */
|
||||
extern const unsigned char flags_none[MAX_INSN_FLGS + 1];
|
||||
extern const unsigned char flags_f[MAX_INSN_FLGS + 1];
|
||||
extern const unsigned char flags_cc[MAX_INSN_FLGS + 1];
|
||||
extern const unsigned char flags_ccf[MAX_INSN_FLGS + 1];
|
||||
|
||||
extern const unsigned char arg_none[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_rarbrc[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_zarbrc[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_rbrbrc[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_rarbu6[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_zarbu6[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_rbrbu6[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_rbrbs12[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_ralimmrc[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_rarblimm[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_zalimmrc[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_zarblimm[MAX_INSN_ARGS + 1];
|
||||
|
||||
extern const unsigned char arg_32bit_rbrblimm[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_ralimmu6[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_zalimmu6[MAX_INSN_ARGS + 1];
|
||||
|
||||
extern const unsigned char arg_32bit_zalimms12[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_ralimmlimm[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_zalimmlimm[MAX_INSN_ARGS + 1];
|
||||
|
||||
extern const unsigned char arg_32bit_rbrc[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_zarc[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_rbu6[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_zau6[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_rblimm[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_zalimm[MAX_INSN_ARGS + 1];
|
||||
|
||||
extern const unsigned char arg_32bit_limmrc[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_limmu6[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_limms12[MAX_INSN_ARGS + 1];
|
||||
extern const unsigned char arg_32bit_limmlimm[MAX_INSN_ARGS + 1];
|
||||
|
||||
#endif /* OPCODE_ARC_H */
|
||||
|
|
|
@ -1,3 +1,34 @@
|
|||
2016-04-12 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* arc-opc.c (flags_none, flags_f, flags_cc, flags_ccf):
|
||||
Initialize.
|
||||
(arg_none, arg_32bit_rarbrc, arg_32bit_zarbrc, arg_32bit_rbrbrc)
|
||||
(arg_32bit_rarbu6, arg_32bit_zarbu6, arg_32bit_rbrbu6)
|
||||
(arg_32bit_rbrbs12, arg_32bit_ralimmrc, arg_32bit_rarblimm)
|
||||
(arg_32bit_zalimmrc, arg_32bit_zarblimm, arg_32bit_rbrblimm)
|
||||
(arg_32bit_ralimmu6, arg_32bit_zalimmu6, arg_32bit_zalimms12)
|
||||
(arg_32bit_ralimmlimm, arg_32bit_zalimmlimm, arg_32bit_rbrc)
|
||||
(arg_32bit_zarc, arg_32bit_rbu6, arg_32bit_zau6, arg_32bit_rblimm)
|
||||
(arg_32bit_zalimm, arg_32bit_limmrc, arg_32bit_limmu6)
|
||||
(arg_32bit_limms12, arg_32bit_limmlimm): Likewise.
|
||||
(arc_opcode arc_opcodes): Null terminate the array.
|
||||
(arc_num_opcodes): Remove.
|
||||
* arc-ext.h (INSERT_XOP): Define.
|
||||
(extInstruction_t): Likewise.
|
||||
(arcExtMap_instName): Delete.
|
||||
(arcExtMap_insn): New function.
|
||||
(arcExtMap_genOpcode): Likewise.
|
||||
* arc-ext.c (ExtInstruction): Remove.
|
||||
(create_map): Zero initialize instruction fields.
|
||||
(arcExtMap_instName): Remove.
|
||||
(arcExtMap_insn): New function.
|
||||
(dump_ARC_extmap): More info while debuging.
|
||||
(arcExtMap_genOpcode): New function.
|
||||
* arc-dis.c (find_format): New function.
|
||||
(print_insn_arc): Use find_format.
|
||||
(arc_get_disassembler): Enable dump_ARC_extmap only when
|
||||
debugging.
|
||||
|
||||
2016-04-11 Maciej W. Rozycki <macro@imgtec.com>
|
||||
|
||||
* mips-dis.c (print_mips16_insn_arg): Mask unused extended
|
||||
|
@ -27,12 +58,12 @@
|
|||
|
||||
2016-04-05 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* arc-regs.h: Add a new subclass field. Add double assist
|
||||
accumulator register values.
|
||||
* arc-tbl.h: Use DPA subclass to mark the double assist
|
||||
instructions. Use DPX/SPX subclas to mark the FPX instructions.
|
||||
* arc-opc.c (RSP): Define instead of SP.
|
||||
(arc_aux_regs): Add the subclass field.
|
||||
* arc-regs.h: Add a new subclass field. Add double assist
|
||||
accumulator register values.
|
||||
* arc-tbl.h: Use DPA subclass to mark the double assist
|
||||
instructions. Use DPX/SPX subclas to mark the FPX instructions.
|
||||
* arc-opc.c (RSP): Define instead of SP.
|
||||
(arc_aux_regs): Add the subclass field.
|
||||
|
||||
2016-04-05 Jiong Wang <jiong.wang@arm.com>
|
||||
|
||||
|
@ -50,23 +81,23 @@
|
|||
|
||||
2016-03-30 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* arc-regs.h (IC_RAM_ADDRESS, IC_TAG, IC_WP, IC_DATA, CONTROL0)
|
||||
(AX2, AY2, MX2, MY2, AY0, AY1, DC_RAM_ADDR, DC_TAG, CONTROL1)
|
||||
(RTT): Remove duplicate.
|
||||
(LCDINSTR, LCDDATA, LCDSTAT, CC_*, PCT_COUNT*, PCT_SNAP*)
|
||||
(PCT_CONFIG*): Remove.
|
||||
(D1L, D1H, D2H, D2L): Define.
|
||||
* arc-regs.h (IC_RAM_ADDRESS, IC_TAG, IC_WP, IC_DATA, CONTROL0)
|
||||
(AX2, AY2, MX2, MY2, AY0, AY1, DC_RAM_ADDR, DC_TAG, CONTROL1)
|
||||
(RTT): Remove duplicate.
|
||||
(LCDINSTR, LCDDATA, LCDSTAT, CC_*, PCT_COUNT*, PCT_SNAP*)
|
||||
(PCT_CONFIG*): Remove.
|
||||
(D1L, D1H, D2H, D2L): Define.
|
||||
|
||||
2016-03-29 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* arc-ext-tbl.h (dsp_fp_i2flt): Fix typo.
|
||||
* arc-ext-tbl.h (dsp_fp_i2flt): Fix typo.
|
||||
|
||||
2016-03-29 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* arc-tbl.h (invld07): Remove.
|
||||
* arc-ext-tbl.h: New file.
|
||||
* arc-dis.c (FIELDA, FIELDB, FIELDC): Remove.
|
||||
* arc-opc.c (arc_opcodes): Add ext-tbl include.
|
||||
* arc-tbl.h (invld07): Remove.
|
||||
* arc-ext-tbl.h: New file.
|
||||
* arc-dis.c (FIELDA, FIELDB, FIELDC): Remove.
|
||||
* arc-opc.c (arc_opcodes): Add ext-tbl include.
|
||||
|
||||
2016-03-24 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
|
@ -164,8 +195,8 @@
|
|||
2016-02-10 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
Janek van Oirschot <jvanoirs@synopsys.com>
|
||||
|
||||
* arc-opc.c (arc_relax_opcodes, arc_num_relax_opcodes): New
|
||||
variable.
|
||||
* arc-opc.c (arc_relax_opcodes, arc_num_relax_opcodes): New
|
||||
variable.
|
||||
|
||||
2016-02-04 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
|
|
|
@ -102,6 +102,107 @@ special_flag_p (const char *opname,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Find proper format for the given opcode. */
|
||||
static const struct arc_opcode *
|
||||
find_format (const struct arc_opcode *arc_table,
|
||||
unsigned *insn, int insnLen,
|
||||
unsigned isa_mask)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
const struct arc_opcode *opcode = NULL;
|
||||
const unsigned char *opidx;
|
||||
const unsigned char *flgidx;
|
||||
|
||||
do {
|
||||
bfd_boolean invalid = FALSE;
|
||||
|
||||
opcode = &arc_table[i++];
|
||||
|
||||
if (ARC_SHORT (opcode->mask) && (insnLen == 2))
|
||||
{
|
||||
if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
|
||||
continue;
|
||||
}
|
||||
else if (!ARC_SHORT (opcode->mask) && (insnLen == 4))
|
||||
{
|
||||
if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
if ((insn[0] ^ opcode->opcode) & opcode->mask)
|
||||
continue;
|
||||
|
||||
if (!(opcode->cpu & isa_mask))
|
||||
continue;
|
||||
|
||||
/* Possible candidate, check the operands. */
|
||||
for (opidx = opcode->operands; *opidx; opidx++)
|
||||
{
|
||||
int value;
|
||||
const struct arc_operand *operand = &arc_operands[*opidx];
|
||||
|
||||
if (operand->flags & ARC_OPERAND_FAKE)
|
||||
continue;
|
||||
|
||||
if (operand->extract)
|
||||
value = (*operand->extract) (insn[0], &invalid);
|
||||
else
|
||||
value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
|
||||
|
||||
/* Check for LIMM indicator. If it is there, then make sure
|
||||
we pick the right format. */
|
||||
if (operand->flags & ARC_OPERAND_IR
|
||||
&& !(operand->flags & ARC_OPERAND_LIMM))
|
||||
{
|
||||
if ((value == 0x3E && insnLen == 4)
|
||||
|| (value == 0x1E && insnLen == 2))
|
||||
{
|
||||
invalid = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the flags. */
|
||||
for (flgidx = opcode->flags; *flgidx; flgidx++)
|
||||
{
|
||||
/* Get a valid flag class. */
|
||||
const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
|
||||
const unsigned *flgopridx;
|
||||
int foundA = 0, foundB = 0;
|
||||
|
||||
for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
|
||||
{
|
||||
const struct arc_flag_operand *flg_operand =
|
||||
&arc_flag_operands[*flgopridx];
|
||||
unsigned int value;
|
||||
|
||||
value = (insn[0] >> flg_operand->shift)
|
||||
& ((1 << flg_operand->bits) - 1);
|
||||
if (value == flg_operand->code)
|
||||
foundA = 1;
|
||||
if (value)
|
||||
foundB = 1;
|
||||
}
|
||||
if (!foundA && foundB)
|
||||
{
|
||||
invalid = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalid)
|
||||
continue;
|
||||
|
||||
/* The instruction is valid. */
|
||||
return opcode;
|
||||
} while (opcode->mask);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Disassemble ARC instructions. */
|
||||
|
||||
static int
|
||||
|
@ -111,15 +212,13 @@ print_insn_arc (bfd_vma memaddr,
|
|||
bfd_byte buffer[4];
|
||||
unsigned int lowbyte, highbyte;
|
||||
int status;
|
||||
unsigned int i;
|
||||
int insnLen = 0;
|
||||
unsigned insn[2] = { 0, 0 };
|
||||
unsigned isa_mask;
|
||||
const unsigned char *opidx;
|
||||
const unsigned char *flgidx;
|
||||
const struct arc_opcode *opcode;
|
||||
const char *instrName;
|
||||
int flags;
|
||||
const extInstruction_t *einsn;
|
||||
bfd_boolean need_comma;
|
||||
bfd_boolean open_braket;
|
||||
int size;
|
||||
|
@ -218,7 +317,7 @@ print_insn_arc (bfd_vma memaddr,
|
|||
return size;
|
||||
}
|
||||
|
||||
if ( (((buffer[lowbyte] & 0xf8) > 0x38)
|
||||
if ((((buffer[lowbyte] & 0xf8) > 0x38)
|
||||
&& ((buffer[lowbyte] & 0xf8) != 0x48))
|
||||
|| ((info->mach == bfd_mach_arc_arcv2)
|
||||
&& ((buffer[lowbyte] & 0xF8) == 0x48)) /* FIXME! ugly. */
|
||||
|
@ -254,110 +353,40 @@ print_insn_arc (bfd_vma memaddr,
|
|||
info->disassembler_needs_relocs = TRUE;
|
||||
|
||||
/* Find the first match in the opcode table. */
|
||||
for (i = 0; i < arc_num_opcodes; i++)
|
||||
opcode = find_format (arc_opcodes, insn, insnLen, isa_mask);
|
||||
|
||||
if (!opcode)
|
||||
{
|
||||
bfd_boolean invalid = FALSE;
|
||||
|
||||
opcode = &arc_opcodes[i];
|
||||
|
||||
if (ARC_SHORT (opcode->mask) && (insnLen == 2))
|
||||
/* No instruction found. Try the extensions. */
|
||||
einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]);
|
||||
if (einsn)
|
||||
{
|
||||
if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
|
||||
continue;
|
||||
}
|
||||
else if (!ARC_SHORT (opcode->mask) && (insnLen == 4))
|
||||
{
|
||||
if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
|
||||
continue;
|
||||
const char *errmsg = NULL;
|
||||
opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg);
|
||||
if (opcode == NULL)
|
||||
{
|
||||
(*info->fprintf_func) (info->stream,
|
||||
"An error occured while "
|
||||
"generating the extension instruction "
|
||||
"operations");
|
||||
return -1;
|
||||
}
|
||||
|
||||
opcode = find_format (opcode, insn, insnLen, isa_mask);
|
||||
assert (opcode != NULL);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
if ((insn[0] ^ opcode->opcode) & opcode->mask)
|
||||
continue;
|
||||
|
||||
if (!(opcode->cpu & isa_mask))
|
||||
continue;
|
||||
|
||||
/* Possible candidate, check the operands. */
|
||||
for (opidx = opcode->operands; *opidx; opidx++)
|
||||
{
|
||||
int value;
|
||||
const struct arc_operand *operand = &arc_operands[*opidx];
|
||||
|
||||
if (operand->flags & ARC_OPERAND_FAKE)
|
||||
continue;
|
||||
|
||||
if (operand->extract)
|
||||
value = (*operand->extract) (insn[0], &invalid);
|
||||
if (insnLen == 2)
|
||||
(*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
|
||||
else
|
||||
value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
|
||||
(*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
|
||||
|
||||
/* Check for LIMM indicator. If it is there, then make sure
|
||||
we pick the right format. */
|
||||
if (operand->flags & ARC_OPERAND_IR
|
||||
&& !(operand->flags & ARC_OPERAND_LIMM))
|
||||
{
|
||||
if ((value == 0x3E && insnLen == 4)
|
||||
|| (value == 0x1E && insnLen == 2))
|
||||
{
|
||||
invalid = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
info->insn_type = dis_noninsn;
|
||||
return insnLen;
|
||||
}
|
||||
|
||||
/* Check the flags. */
|
||||
for (flgidx = opcode->flags; *flgidx; flgidx++)
|
||||
{
|
||||
/* Get a valid flag class. */
|
||||
const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
|
||||
const unsigned *flgopridx;
|
||||
int foundA = 0, foundB = 0;
|
||||
|
||||
for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
|
||||
{
|
||||
const struct arc_flag_operand *flg_operand = &arc_flag_operands[*flgopridx];
|
||||
unsigned int value;
|
||||
|
||||
value = (insn[0] >> flg_operand->shift) & ((1 << flg_operand->bits) - 1);
|
||||
if (value == flg_operand->code)
|
||||
foundA = 1;
|
||||
if (value)
|
||||
foundB = 1;
|
||||
}
|
||||
if (!foundA && foundB)
|
||||
{
|
||||
invalid = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalid)
|
||||
continue;
|
||||
|
||||
/* The instruction is valid. */
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* No instruction found. Try the extenssions. */
|
||||
instrName = arcExtMap_instName (OPCODE (insn[0]), insn[0], &flags);
|
||||
if (instrName)
|
||||
{
|
||||
opcode = &arc_opcodes[0];
|
||||
(*info->fprintf_func) (info->stream, "%s", instrName);
|
||||
goto print_flags;
|
||||
}
|
||||
|
||||
if (insnLen == 2)
|
||||
(*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
|
||||
else
|
||||
(*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
|
||||
|
||||
info->insn_type = dis_noninsn;
|
||||
return insnLen;
|
||||
|
||||
found:
|
||||
/* Print the mnemonic. */
|
||||
(*info->fprintf_func) (info->stream, "%s", opcode->name);
|
||||
|
||||
|
@ -382,7 +411,6 @@ print_insn_arc (bfd_vma memaddr,
|
|||
|
||||
pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
|
||||
|
||||
print_flags:
|
||||
/* Now extract and print the flags. */
|
||||
for (flgidx = opcode->flags; *flgidx; flgidx++)
|
||||
{
|
||||
|
@ -557,7 +585,9 @@ arc_get_disassembler (bfd *abfd)
|
|||
{
|
||||
/* Read the extenssion insns and registers, if any. */
|
||||
build_ARC_extmap (abfd);
|
||||
#ifdef DEBUG
|
||||
dump_ARC_extmap ();
|
||||
#endif
|
||||
|
||||
return print_insn_arc;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "elf/arc.h"
|
||||
#include "libiberty.h"
|
||||
|
||||
|
||||
/* This module provides support for extensions to the ARC processor
|
||||
architecture. */
|
||||
|
||||
|
@ -52,15 +51,6 @@
|
|||
|
||||
/* These types define the information stored in the table. */
|
||||
|
||||
struct ExtInstruction
|
||||
{
|
||||
char major;
|
||||
char minor;
|
||||
char flags;
|
||||
char* name;
|
||||
struct ExtInstruction* next;
|
||||
};
|
||||
|
||||
struct ExtAuxRegister
|
||||
{
|
||||
long address;
|
||||
|
@ -141,6 +131,9 @@ create_map (unsigned char *block,
|
|||
insn->minor = minor;
|
||||
insn->flags = p[4];
|
||||
insn->next = *bucket;
|
||||
insn->suffix = 0;
|
||||
insn->syntax = 0;
|
||||
insn->modsyn = 0;
|
||||
*bucket = insn;
|
||||
break;
|
||||
}
|
||||
|
@ -285,10 +278,8 @@ ExtReadWrite_image (enum ExtReadWrite val)
|
|||
|
||||
/* Get the name of an extension instruction. */
|
||||
|
||||
const char *
|
||||
arcExtMap_instName (int opcode,
|
||||
int insn,
|
||||
int *flags)
|
||||
const extInstruction_t *
|
||||
arcExtMap_insn (int opcode, int insn)
|
||||
{
|
||||
/* Here the following tasks need to be done. First of all, the
|
||||
opcode stored in the Extension Map is the real opcode. However,
|
||||
|
@ -306,7 +297,7 @@ arcExtMap_instName (int opcode,
|
|||
then un-mangle using iiiiiI else iiiiii. */
|
||||
|
||||
unsigned char minor;
|
||||
struct ExtInstruction *temp;
|
||||
extInstruction_t *temp;
|
||||
|
||||
/* 16-bit instructions. */
|
||||
if (0x08 <= opcode && opcode <= 0x0b)
|
||||
|
@ -367,8 +358,7 @@ arcExtMap_instName (int opcode,
|
|||
{
|
||||
if ((temp->major == opcode) && (temp->minor == minor))
|
||||
{
|
||||
*flags = temp->flags;
|
||||
return temp->name;
|
||||
return temp;
|
||||
}
|
||||
temp = temp->next;
|
||||
}
|
||||
|
@ -459,6 +449,8 @@ build_ARC_extmap (bfd *text_bfd)
|
|||
}
|
||||
}
|
||||
|
||||
/* Debug function used to dump the ARC information fount in arcextmap
|
||||
sections. */
|
||||
|
||||
void
|
||||
dump_ARC_extmap (void)
|
||||
|
@ -480,8 +472,20 @@ dump_ARC_extmap (void)
|
|||
|
||||
for (insn = arc_extension_map.instructions[i];
|
||||
insn != NULL; insn = insn->next)
|
||||
printf ("INST: %d %d %x %s\n", insn->major, insn->minor,
|
||||
insn->flags, insn->name);
|
||||
{
|
||||
printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
|
||||
if (insn->flags & ARC_SYNTAX_2OP)
|
||||
printf ("SYNTAX_2OP");
|
||||
else if (insn->flags & ARC_SYNTAX_3OP)
|
||||
printf ("SYNTAX_3OP");
|
||||
else
|
||||
printf ("SYNTAX_UNK");
|
||||
|
||||
if (insn->flags & 0x10)
|
||||
printf ("|MODIFIER");
|
||||
|
||||
printf (" %s\n", insn->name);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_EXT_CORE; i++)
|
||||
|
@ -497,3 +501,267 @@ dump_ARC_extmap (void)
|
|||
if (arc_extension_map.condCodes[i])
|
||||
printf ("COND: %s\n", arc_extension_map.condCodes[i]);
|
||||
}
|
||||
|
||||
/* For a given extension instruction generate the equivalent arc
|
||||
opcode structure. */
|
||||
|
||||
struct arc_opcode *
|
||||
arcExtMap_genOpcode (const extInstruction_t *einsn,
|
||||
unsigned arc_target,
|
||||
const char **errmsg)
|
||||
{
|
||||
struct arc_opcode *q, *arc_ext_opcodes = NULL;
|
||||
const unsigned char *lflags_f;
|
||||
const unsigned char *lflags_ccf;
|
||||
int count;
|
||||
|
||||
/* Check for the class to see how many instructions we generate. */
|
||||
switch (einsn->flags & (ARC_SYNTAX_3OP | ARC_SYNTAX_2OP))
|
||||
{
|
||||
case ARC_SYNTAX_3OP:
|
||||
count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
|
||||
break;
|
||||
case ARC_SYNTAX_2OP:
|
||||
count = (einsn->flags & 0x10) ? 7 : 6;
|
||||
break;
|
||||
default:
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Allocate memory. */
|
||||
arc_ext_opcodes = (struct arc_opcode *)
|
||||
xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
|
||||
|
||||
if (arc_ext_opcodes == NULL)
|
||||
{
|
||||
*errmsg = "Virtual memory exhausted";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Generate the patterns. */
|
||||
q = arc_ext_opcodes;
|
||||
|
||||
if (einsn->suffix)
|
||||
{
|
||||
lflags_f = flags_none;
|
||||
lflags_ccf = flags_none;
|
||||
}
|
||||
else
|
||||
{
|
||||
lflags_f = flags_f;
|
||||
lflags_ccf = flags_ccf;
|
||||
}
|
||||
|
||||
if (einsn->suffix & ARC_SUFFIX_COND)
|
||||
lflags_ccf = flags_cc;
|
||||
if (einsn->suffix & ARC_SUFFIX_FLAG)
|
||||
{
|
||||
lflags_f = flags_f;
|
||||
lflags_ccf = flags_f;
|
||||
}
|
||||
if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
|
||||
lflags_ccf = flags_ccf;
|
||||
|
||||
if (einsn->flags & ARC_SYNTAX_2OP
|
||||
&& !(einsn->flags & 0x10))
|
||||
{
|
||||
/* Regular 2OP instruction. */
|
||||
if (einsn->suffix & ARC_SUFFIX_COND)
|
||||
*errmsg = "Suffix SUFFIX_COND ignored";
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
|
||||
arc_target, arg_32bit_rbrc, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
|
||||
arc_target, arg_32bit_zarc, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
|
||||
arc_target, arg_32bit_rbu6, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
|
||||
arc_target, arg_32bit_zau6, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
|
||||
arc_target, arg_32bit_rblimm, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
|
||||
arc_target, arg_32bit_zalimm, lflags_f);
|
||||
}
|
||||
else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
|
||||
{
|
||||
/* This is actually a 3OP pattern. The first operand is
|
||||
immplied and is set to zero. */
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
|
||||
arc_target, arg_32bit_rbrc, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
|
||||
arc_target, arg_32bit_rbu6, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
|
||||
arc_target, arg_32bit_rblimm, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
|
||||
arc_target, arg_32bit_limmrc, lflags_ccf);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
|
||||
arc_target, arg_32bit_limmu6, lflags_ccf);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
|
||||
arc_target, arg_32bit_limms12, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
|
||||
arc_target, arg_32bit_limmlimm, lflags_ccf);
|
||||
}
|
||||
else if (einsn->flags & ARC_SYNTAX_3OP
|
||||
&& !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
|
||||
{
|
||||
/* Regular 3OP instruction. */
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_ABC (einsn->major, einsn->minor), MINSN3OP_ABC,
|
||||
arc_target, arg_32bit_rarbrc, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
|
||||
arc_target, arg_32bit_zarbrc, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
|
||||
arc_target, arg_32bit_rbrbrc, lflags_ccf);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_ABU (einsn->major, einsn->minor), MINSN3OP_ABU,
|
||||
arc_target, arg_32bit_rarbu6, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
|
||||
arc_target, arg_32bit_zarbu6, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
|
||||
arc_target, arg_32bit_rbrbu6, lflags_ccf);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_BBS (einsn->major, einsn->minor), MINSN3OP_BBS,
|
||||
arc_target, arg_32bit_rbrbs12, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_ALC (einsn->major, einsn->minor), MINSN3OP_ALC,
|
||||
arc_target, arg_32bit_ralimmrc, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_ABL (einsn->major, einsn->minor), MINSN3OP_ABL,
|
||||
arc_target, arg_32bit_rarblimm, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC,
|
||||
arc_target, arg_32bit_zalimmrc, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
|
||||
arc_target, arg_32bit_zarblimm, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
|
||||
arc_target, arg_32bit_zalimmrc, lflags_ccf);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
|
||||
arc_target, arg_32bit_rbrblimm, lflags_ccf);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_ALU (einsn->major, einsn->minor), MINSN3OP_ALU,
|
||||
arc_target, arg_32bit_ralimmu6, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU,
|
||||
arc_target, arg_32bit_zalimmu6, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
|
||||
arc_target, arg_32bit_zalimmu6, lflags_ccf);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
|
||||
arc_target, arg_32bit_zalimms12, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_ALL (einsn->major, einsn->minor), MINSN3OP_ALL,
|
||||
arc_target, arg_32bit_ralimmlimm, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL,
|
||||
arc_target, arg_32bit_zalimmlimm, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
|
||||
arc_target, arg_32bit_zalimmlimm, lflags_ccf);
|
||||
}
|
||||
else if (einsn->flags & ARC_SYNTAX_3OP)
|
||||
{
|
||||
/* 3OP instruction which accepts only zero as first
|
||||
argument. */
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
|
||||
arc_target, arg_32bit_zarbrc, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
|
||||
arc_target, arg_32bit_zarbu6, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC,
|
||||
arc_target, arg_32bit_zalimmrc, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
|
||||
arc_target, arg_32bit_zarblimm, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
|
||||
arc_target, arg_32bit_zalimmrc, lflags_ccf);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU,
|
||||
arc_target, arg_32bit_zalimmu6, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
|
||||
arc_target, arg_32bit_zalimmu6, lflags_ccf);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
|
||||
arc_target, arg_32bit_zalimms12, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL,
|
||||
arc_target, arg_32bit_zalimmlimm, lflags_f);
|
||||
|
||||
INSERT_XOP (q, einsn->name,
|
||||
INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
|
||||
arc_target, arg_32bit_zalimmlimm, lflags_ccf);
|
||||
}
|
||||
else
|
||||
{
|
||||
*errmsg = "Unknown syntax";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* End marker. */
|
||||
memset (q, 0, sizeof (*arc_ext_opcodes));
|
||||
|
||||
return arc_ext_opcodes;
|
||||
}
|
||||
|
|
|
@ -39,13 +39,14 @@
|
|||
#ifndef ARC_EXTENSIONS_H
|
||||
#define ARC_EXTENSIONS_H
|
||||
|
||||
#include "opcode/arc.h"
|
||||
|
||||
#define IGNORE_FIRST_OPD 1
|
||||
|
||||
/* Define this if we do not want to encode instructions based on the
|
||||
ARCompact Programmer's Reference. */
|
||||
#define UNMANGLED
|
||||
|
||||
|
||||
/* This defines the kinds of extensions which may be read from the
|
||||
ections in the executable files. */
|
||||
enum ExtOperType
|
||||
|
@ -63,7 +64,6 @@ enum ExtOperType
|
|||
EXT_CORE_REGISTER_CLASS = 9
|
||||
};
|
||||
|
||||
|
||||
enum ExtReadWrite
|
||||
{
|
||||
REG_INVALID,
|
||||
|
@ -72,6 +72,48 @@ enum ExtReadWrite
|
|||
REG_READWRITE
|
||||
};
|
||||
|
||||
/* Macro used when generating the patterns for an extension
|
||||
instruction. */
|
||||
#define INSERT_XOP(OP, NAME, CODE, MASK, CPU, ARG, FLG) \
|
||||
do { \
|
||||
(OP)->name = NAME; \
|
||||
(OP)->opcode = CODE; \
|
||||
(OP)->mask = MASK; \
|
||||
(OP)->cpu = CPU; \
|
||||
(OP)->class = ARITH; \
|
||||
(OP)->subclass = NONE; \
|
||||
memcpy ((OP)->operands, (ARG), MAX_INSN_ARGS); \
|
||||
memcpy ((OP)->flags, (FLG), MAX_INSN_FLGS); \
|
||||
(OP++); \
|
||||
} while (0)
|
||||
|
||||
/* Typedef to hold the extension instruction definition. */
|
||||
typedef struct ExtInstruction
|
||||
{
|
||||
/* Name. */
|
||||
char *name;
|
||||
|
||||
/* Major opcode. */
|
||||
char major;
|
||||
|
||||
/* Minor(sub) opcode. */
|
||||
char minor;
|
||||
|
||||
/* Flags, holds the syntax class and modifiers. */
|
||||
char flags;
|
||||
|
||||
/* Syntax class. Use by assembler. */
|
||||
unsigned char syntax;
|
||||
|
||||
/* Syntax class modifier. Used by assembler. */
|
||||
unsigned char modsyn;
|
||||
|
||||
/* Suffix class. Used by assembler. */
|
||||
unsigned char suffix;
|
||||
|
||||
/* Pointer to the next extension instruction. */
|
||||
struct ExtInstruction* next;
|
||||
} extInstruction_t;
|
||||
|
||||
/* Constructor function. */
|
||||
extern void build_ARC_extmap (bfd *);
|
||||
|
@ -81,7 +123,10 @@ extern enum ExtReadWrite arcExtMap_coreReadWrite (int);
|
|||
extern const char * arcExtMap_coreRegName (int);
|
||||
extern const char * arcExtMap_auxRegName (long);
|
||||
extern const char * arcExtMap_condCodeName (int);
|
||||
extern const char * arcExtMap_instName (int, int, int *);
|
||||
extern const extInstruction_t *arcExtMap_insn (int, int);
|
||||
extern struct arc_opcode *arcExtMap_genOpcode (const extInstruction_t *,
|
||||
unsigned arc_target,
|
||||
const char **errmsg);
|
||||
|
||||
/* Dump function (for debugging). */
|
||||
extern void dump_ARC_extmap (void);
|
||||
|
|
|
@ -1136,6 +1136,11 @@ const struct arc_flag_class arc_flag_classes[] =
|
|||
|
||||
};
|
||||
|
||||
const unsigned char flags_none[] = { 0 };
|
||||
const unsigned char flags_f[] = { C_F };
|
||||
const unsigned char flags_cc[] = { C_CC };
|
||||
const unsigned char flags_ccf[] = { C_CC, C_F };
|
||||
|
||||
/* The operands table.
|
||||
|
||||
The format of the operands table is:
|
||||
|
@ -1499,6 +1504,39 @@ const unsigned arc_num_operands = ARRAY_SIZE (arc_operands);
|
|||
const unsigned arc_Toperand = FKT_T;
|
||||
const unsigned arc_NToperand = FKT_NT;
|
||||
|
||||
const unsigned char arg_none[] = { 0 };
|
||||
const unsigned char arg_32bit_rarbrc[] = { RA, RB, RC };
|
||||
const unsigned char arg_32bit_zarbrc[] = { ZA, RB, RC };
|
||||
const unsigned char arg_32bit_rbrbrc[] = { RB, RBdup, RC };
|
||||
const unsigned char arg_32bit_rarbu6[] = { RA, RB, UIMM6_20 };
|
||||
const unsigned char arg_32bit_zarbu6[] = { ZA, RB, UIMM6_20 };
|
||||
const unsigned char arg_32bit_rbrbu6[] = { RB, RBdup, UIMM6_20 };
|
||||
const unsigned char arg_32bit_rbrbs12[] = { RB, RBdup, SIMM12_20 };
|
||||
const unsigned char arg_32bit_ralimmrc[] = { RA, LIMM, RC };
|
||||
const unsigned char arg_32bit_rarblimm[] = { RA, RB, LIMM };
|
||||
const unsigned char arg_32bit_zalimmrc[] = { ZA, LIMM, RC };
|
||||
const unsigned char arg_32bit_zarblimm[] = { ZA, RB, LIMM };
|
||||
|
||||
const unsigned char arg_32bit_rbrblimm[] = { RB, RBdup, LIMM };
|
||||
const unsigned char arg_32bit_ralimmu6[] = { RA, LIMM, UIMM6_20 };
|
||||
const unsigned char arg_32bit_zalimmu6[] = { ZA, LIMM, UIMM6_20 };
|
||||
|
||||
const unsigned char arg_32bit_zalimms12[] = { ZA, LIMM, SIMM12_20 };
|
||||
const unsigned char arg_32bit_ralimmlimm[] = { RA, LIMM, LIMMdup };
|
||||
const unsigned char arg_32bit_zalimmlimm[] = { ZA, LIMM, LIMMdup };
|
||||
|
||||
const unsigned char arg_32bit_rbrc[] = { RB, RC };
|
||||
const unsigned char arg_32bit_zarc[] = { ZA, RC };
|
||||
const unsigned char arg_32bit_rbu6[] = { RB, UIMM6_20 };
|
||||
const unsigned char arg_32bit_zau6[] = { ZA, UIMM6_20 };
|
||||
const unsigned char arg_32bit_rblimm[] = { RB, LIMM };
|
||||
const unsigned char arg_32bit_zalimm[] = { ZA, LIMM };
|
||||
|
||||
const unsigned char arg_32bit_limmrc[] = { LIMM, RC };
|
||||
const unsigned char arg_32bit_limmu6[] = { LIMM, UIMM6_20 };
|
||||
const unsigned char arg_32bit_limms12[] = { LIMM, SIMM12_20 };
|
||||
const unsigned char arg_32bit_limmlimm[] = { LIMM, LIMMdup };
|
||||
|
||||
/* The opcode table.
|
||||
|
||||
The format of the opcode table is:
|
||||
|
@ -1539,9 +1577,9 @@ const struct arc_opcode arc_opcodes[] =
|
|||
#include "arc-tbl.h"
|
||||
#include "arc-nps400-tbl.h"
|
||||
#include "arc-ext-tbl.h"
|
||||
};
|
||||
|
||||
const unsigned arc_num_opcodes = ARRAY_SIZE (arc_opcodes);
|
||||
{ NULL, 0, 0, 0, 0, 0, { 0 }, { 0 } }
|
||||
};
|
||||
|
||||
/* List with special cases instructions and the applicable flags. */
|
||||
const struct arc_flag_special arc_flag_special_cases[] =
|
||||
|
|
Loading…
Reference in New Issue