version 1.1.1.2, 2016/10/26 17:03:29 |
version 1.1.1.3, 2018/04/14 15:37:15 |
|
|
/* ARC target-dependent stuff. Extension structure access functions |
/* ARC target-dependent stuff. Extension structure access functions |
Copyright (C) 1995-2015 Free Software Foundation, Inc. |
Copyright (C) 1995-2016 Free Software Foundation, Inc. |
|
|
This file is part of libopcodes. |
This file is part of libopcodes. |
|
|
|
|
#include "elf/arc.h" |
#include "elf/arc.h" |
#include "libiberty.h" |
#include "libiberty.h" |
|
|
|
|
/* This module provides support for extensions to the ARC processor |
/* This module provides support for extensions to the ARC processor |
architecture. */ |
architecture. */ |
|
|
|
|
|
|
/* These types define the information stored in the table. */ |
/* These types define the information stored in the table. */ |
|
|
struct ExtInstruction |
|
{ |
|
char major; |
|
char minor; |
|
char flags; |
|
char* name; |
|
struct ExtInstruction* next; |
|
}; |
|
|
|
struct ExtAuxRegister |
struct ExtAuxRegister |
{ |
{ |
long address; |
long address; |
Line 141 create_map (unsigned char *block, |
|
Line 131 create_map (unsigned char *block, |
|
insn->minor = minor; |
insn->minor = minor; |
insn->flags = p[4]; |
insn->flags = p[4]; |
insn->next = *bucket; |
insn->next = *bucket; |
|
insn->suffix = 0; |
|
insn->syntax = 0; |
|
insn->modsyn = 0; |
*bucket = insn; |
*bucket = insn; |
break; |
break; |
} |
} |
Line 285 ExtReadWrite_image (enum ExtReadWrite va |
|
Line 278 ExtReadWrite_image (enum ExtReadWrite va |
|
|
|
/* Get the name of an extension instruction. */ |
/* Get the name of an extension instruction. */ |
|
|
const char * |
const extInstruction_t * |
arcExtMap_instName (int opcode, |
arcExtMap_insn (int opcode, int insn) |
int insn, |
|
int *flags) |
|
{ |
{ |
/* Here the following tasks need to be done. First of all, the |
/* Here the following tasks need to be done. First of all, the |
opcode stored in the Extension Map is the real opcode. However, |
opcode stored in the Extension Map is the real opcode. However, |
Line 306 arcExtMap_instName (int opcode, |
|
Line 297 arcExtMap_instName (int opcode, |
|
then un-mangle using iiiiiI else iiiiii. */ |
then un-mangle using iiiiiI else iiiiii. */ |
|
|
unsigned char minor; |
unsigned char minor; |
struct ExtInstruction *temp; |
extInstruction_t *temp; |
|
|
/* 16-bit instructions. */ |
/* 16-bit instructions. */ |
if (0x08 <= opcode && opcode <= 0x0b) |
if (0x08 <= opcode && opcode <= 0x0b) |
Line 367 arcExtMap_instName (int opcode, |
|
Line 358 arcExtMap_instName (int opcode, |
|
{ |
{ |
if ((temp->major == opcode) && (temp->minor == minor)) |
if ((temp->major == opcode) && (temp->minor == minor)) |
{ |
{ |
*flags = temp->flags; |
return temp; |
return temp->name; |
|
} |
} |
temp = temp->next; |
temp = temp->next; |
} |
} |
|
|
arcExtMap_coreRegName (int regnum) |
arcExtMap_coreRegName (int regnum) |
{ |
{ |
if (regnum < FIRST_EXTENSION_CORE_REGISTER |
if (regnum < FIRST_EXTENSION_CORE_REGISTER |
|| regnum > LAST_EXTENSION_CONDITION_CODE) |
|| regnum > LAST_EXTENSION_CORE_REGISTER) |
return NULL; |
return NULL; |
return arc_extension_map. |
return arc_extension_map. |
coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name; |
coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name; |
Line 394 enum ExtReadWrite |
|
Line 384 enum ExtReadWrite |
|
arcExtMap_coreReadWrite (int regnum) |
arcExtMap_coreReadWrite (int regnum) |
{ |
{ |
if (regnum < FIRST_EXTENSION_CORE_REGISTER |
if (regnum < FIRST_EXTENSION_CORE_REGISTER |
|| regnum > LAST_EXTENSION_CONDITION_CODE) |
|| regnum > LAST_EXTENSION_CORE_REGISTER) |
return REG_INVALID; |
return REG_INVALID; |
return arc_extension_map. |
return arc_extension_map. |
coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw; |
coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw; |
Line 459 build_ARC_extmap (bfd *text_bfd) |
|
Line 449 build_ARC_extmap (bfd *text_bfd) |
|
} |
} |
} |
} |
|
|
|
/* Debug function used to dump the ARC information fount in arcextmap |
|
sections. */ |
|
|
void |
void |
dump_ARC_extmap (void) |
dump_ARC_extmap (void) |
Line 480 dump_ARC_extmap (void) |
|
Line 472 dump_ARC_extmap (void) |
|
|
|
for (insn = arc_extension_map.instructions[i]; |
for (insn = arc_extension_map.instructions[i]; |
insn != NULL; insn = insn->next) |
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); |
|
switch (insn->flags & ARC_SYNTAX_MASK) |
|
{ |
|
case ARC_SYNTAX_2OP: |
|
printf ("SYNTAX_2OP"); |
|
break; |
|
case ARC_SYNTAX_3OP: |
|
printf ("SYNTAX_3OP"); |
|
break; |
|
case ARC_SYNTAX_1OP: |
|
printf ("SYNTAX_1OP"); |
|
break; |
|
case ARC_SYNTAX_NOP: |
|
printf ("SYNTAX_NOP"); |
|
break; |
|
default: |
|
printf ("SYNTAX_UNK"); |
|
break; |
|
} |
|
|
|
if (insn->flags & 0x10) |
|
printf ("|MODIFIER"); |
|
|
|
printf (" %s\n", insn->name); |
|
} |
} |
} |
|
|
for (i = 0; i < NUM_EXT_CORE; i++) |
for (i = 0; i < NUM_EXT_CORE; i++) |
Line 489 dump_ARC_extmap (void) |
|
Line 505 dump_ARC_extmap (void) |
|
struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i]; |
struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i]; |
|
|
if (reg.name) |
if (reg.name) |
printf ("CORE: %s %d %s\n", reg.name, reg.number, |
printf ("CORE: 0x%04x %s %s\n", reg.number, |
ExtReadWrite_image (reg.rw)); |
ExtReadWrite_image (reg.rw), |
|
reg.name); |
} |
} |
|
|
for (i = 0; i < NUM_EXT_COND; i++) |
for (i = 0; i < NUM_EXT_COND; i++) |
if (arc_extension_map.condCodes[i]) |
if (arc_extension_map.condCodes[i]) |
printf ("COND: %s\n", 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_MASK) |
|
{ |
|
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; |
|
case ARC_SYNTAX_1OP: |
|
count = 3; |
|
break; |
|
case ARC_SYNTAX_NOP: |
|
count = 1; |
|
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 if (einsn->flags & ARC_SYNTAX_1OP) |
|
{ |
|
if (einsn->suffix & ARC_SUFFIX_COND) |
|
*errmsg = "Suffix SUFFIX_COND ignored"; |
|
|
|
INSERT_XOP (q, einsn->name, |
|
INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor), |
|
MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f); |
|
|
|
INSERT_XOP (q, einsn->name, |
|
INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor) |
|
| (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6, |
|
lflags_f); |
|
|
|
INSERT_XOP (q, einsn->name, |
|
INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor) |
|
| FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm, |
|
lflags_f); |
|
|
|
} |
|
else if (einsn->flags & ARC_SYNTAX_NOP) |
|
{ |
|
if (einsn->suffix & ARC_SUFFIX_COND) |
|
*errmsg = "Suffix SUFFIX_COND ignored"; |
|
|
|
INSERT_XOP (q, einsn->name, |
|
INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor) |
|
| (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f); |
|
} |
|
else |
|
{ |
|
*errmsg = "Unknown syntax"; |
|
return NULL; |
|
} |
|
|
|
/* End marker. */ |
|
memset (q, 0, sizeof (*arc_ext_opcodes)); |
|
|
|
return arc_ext_opcodes; |
|
} |