|
|
|
@ -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; |
|
|
|
} |
|
|
|
|