[ARC] Provide an interface to decode ARC instructions.
gas/ 2017-02-06 Claudiu Zissulescu <claziss@synopsys.com> * config/tc-arc.c (parse_opcode_flags): Ignore implicit flags. include/ 2017-02-06 Claudiu Zissulescu <claziss@synopsys.com> Anton Kolesov <anton.kolesov@synopsys.com> * opcode/arc.h (insn_class_t): Add ENTER, LEAVE, POP, PUSH, BBIT0, BBIT1, BI, BIH, BRCC, EI, JLI, and SUB instruction classes. (flag_class_t): Add F_CLASS_WB, F_CLASS_ZZ, and F_CLASS_IMPLICIT flag classes. opcode/ 2017-02-06 Claudiu Zissulescu <claziss@synopsys.com> Anton Kolesov <anton.kolesov@synopsys.com> * arc-dis.c (arc_disassemble_info): New structure. (init_arc_disasm_info): New function. (find_format_from_table): Ignore implicit flags. (find_format): Update dissassembler private data. (print_flags): Likewise. (print_insn_arc): Likewise. (arc_opcode_to_insn_type): Consider the new added instruction classes. (arcAnalyzeInstr): Remove. (arc_insn_decode): New function. * arc-dis.h (arc_ldst_writeback_mode): New enum. (arc_ldst_data_size): Likewise. (arc_condition_code): Likewise. (arc_operand_kind): Likewise. (arc_insn_kind): New struct. (arc_instruction): Likewise. (arc_insn_decode): Declare function. (ARC_Debugger_OperandType): Deleted. (Flow): Likewise. (NullifyMode): Likewise. (allOperandsSize): Likewise. (arcDisState): Likewise. (arcAnalyzeInstr): Likewise. * arc-dis.c (arc_opcode_to_insn_type): Handle newly introduced insn_class_t enums. * arc-opc.c (F_SIZED): New define. (C_CC_EQ, C_CC_GE, C_CC_GT, C_CC_HI, C_CC_HS): Likewise. (C_CC_LE, C_CC_LO, C_CC_LS, C_CC_LT, C_CC_NE): Likewise. (C_CC_NE, C_AA_AB, C_AA_AW, C_ZZ_D, C_ZZ_H, C_ZZ_B): Likewise. (arc_flag_classes): Add F_CLASS_COND/F_CLASS_IMPLICIT flags. * opcodes/arc-tbl.h: Update instructions to include new F_CLASS_IMPLICIT flags. (bbit0, lp): Change class. (bbit1, bi, bih, br*, ei_s, jli_s): Likewsie
This commit is contained in:
parent
20b477a75c
commit
6ec7c1ae19
@ -1671,6 +1671,10 @@ parse_opcode_flags (const struct arc_opcode *opcode,
|
||||
int cl_matches = 0;
|
||||
struct arc_flags *pflag = NULL;
|
||||
|
||||
/* Check if opcode has implicit flag classes. */
|
||||
if (cl_flags->flag_class & F_CLASS_IMPLICIT)
|
||||
continue;
|
||||
|
||||
/* Check for extension conditional codes. */
|
||||
if (ext_condcode.arc_ext_condcode
|
||||
&& cl_flags->flag_class & F_CLASS_EXTEND)
|
||||
|
@ -42,27 +42,40 @@ typedef enum
|
||||
ACL,
|
||||
ARITH,
|
||||
AUXREG,
|
||||
BBIT0,
|
||||
BBIT1,
|
||||
BI,
|
||||
BIH,
|
||||
BITOP,
|
||||
BITSTREAM,
|
||||
BMU,
|
||||
BRANCH,
|
||||
BRCC,
|
||||
CONTROL,
|
||||
DIVREM,
|
||||
DPI,
|
||||
DSP,
|
||||
EI,
|
||||
ENTER,
|
||||
FLOAT,
|
||||
INVALID,
|
||||
JLI,
|
||||
JUMP,
|
||||
KERNEL,
|
||||
LEAVE,
|
||||
LOAD,
|
||||
LOGICAL,
|
||||
LOOP,
|
||||
MEMORY,
|
||||
MOVE,
|
||||
MPY,
|
||||
NET,
|
||||
PROTOCOL_DECODE,
|
||||
PMU,
|
||||
POP,
|
||||
PUSH,
|
||||
STORE,
|
||||
SUB,
|
||||
XY
|
||||
} insn_class_t;
|
||||
|
||||
@ -111,7 +124,16 @@ typedef enum
|
||||
F_CLASS_EXTEND = (1 << 2),
|
||||
|
||||
/* Condition code flag. */
|
||||
F_CLASS_COND = (1 << 3)
|
||||
F_CLASS_COND = (1 << 3),
|
||||
|
||||
/* Write back mode. */
|
||||
F_CLASS_WB = (1 << 4),
|
||||
|
||||
/* Data size. */
|
||||
F_CLASS_ZZ = (1 << 5),
|
||||
|
||||
/* Implicit flag. */
|
||||
F_CLASS_IMPLICIT = (1 << 6)
|
||||
} flag_class_t;
|
||||
|
||||
/* The opcode table is an array of struct arc_opcode. */
|
||||
|
@ -51,6 +51,33 @@ struct arc_operand_iterator
|
||||
const unsigned char *opidx;
|
||||
};
|
||||
|
||||
/* A private data used by ARC decoder. */
|
||||
struct arc_disassemble_info
|
||||
{
|
||||
/* The current disassembled arc opcode. */
|
||||
const struct arc_opcode *opcode;
|
||||
|
||||
/* Instruction length w/o limm field. */
|
||||
unsigned insn_len;
|
||||
|
||||
/* TRUE if we have limm. */
|
||||
bfd_boolean limm_p;
|
||||
|
||||
/* LIMM value, if exists. */
|
||||
unsigned limm;
|
||||
|
||||
/* Condition code, if exists. */
|
||||
unsigned condition_code;
|
||||
|
||||
/* Writeback mode. */
|
||||
unsigned writeback_mode;
|
||||
|
||||
/* Number of operands. */
|
||||
unsigned operands_count;
|
||||
|
||||
struct arc_insn_operand operands[MAX_INSN_ARGS];
|
||||
};
|
||||
|
||||
/* Globals variables. */
|
||||
|
||||
static const char * const regnames[64] =
|
||||
@ -108,6 +135,20 @@ static linkclass decodelist = NULL;
|
||||
|
||||
/* Functions implementation. */
|
||||
|
||||
/* Initialize private data. */
|
||||
static bfd_boolean
|
||||
init_arc_disasm_info (struct disassemble_info *info)
|
||||
{
|
||||
struct arc_disassemble_info *arc_infop
|
||||
= calloc (sizeof (*arc_infop), 1);
|
||||
|
||||
if (arc_infop == NULL)
|
||||
return FALSE;
|
||||
|
||||
info->private_data = arc_infop;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Add a new element to the decode list. */
|
||||
|
||||
static void
|
||||
@ -280,6 +321,10 @@ find_format_from_table (struct disassemble_info *info,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for the implicit flags. */
|
||||
if (cl_flags->flag_class & F_CLASS_IMPLICIT)
|
||||
continue;
|
||||
|
||||
for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
|
||||
{
|
||||
const struct arc_flag_operand *flg_operand =
|
||||
@ -367,6 +412,7 @@ find_format (bfd_vma memaddr,
|
||||
bfd_boolean needs_limm;
|
||||
const extInstruction_t *einsn, *i;
|
||||
unsigned limm = 0;
|
||||
struct arc_disassemble_info *arc_infop = info->private_data;
|
||||
|
||||
/* First, try the extension instructions. */
|
||||
if (*insn_len == 4)
|
||||
@ -422,6 +468,12 @@ An error occured while generating the extension instruction operations");
|
||||
}
|
||||
|
||||
*opcode_result = opcode;
|
||||
|
||||
/* Update private data. */
|
||||
arc_infop->opcode = opcode;
|
||||
arc_infop->limm = (needs_limm) ? limm : 0;
|
||||
arc_infop->limm_p = needs_limm;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -432,6 +484,7 @@ print_flags (const struct arc_opcode *opcode,
|
||||
{
|
||||
const unsigned char *flgidx;
|
||||
unsigned int value;
|
||||
struct arc_disassemble_info *arc_infop = info->private_data;
|
||||
|
||||
/* Now extract and print the flags. */
|
||||
for (flgidx = opcode->flags; *flgidx; flgidx++)
|
||||
@ -459,6 +512,18 @@ print_flags (const struct arc_opcode *opcode,
|
||||
const struct arc_flag_operand *flg_operand =
|
||||
&arc_flag_operands[*flgopridx];
|
||||
|
||||
/* Implicit flags are only used for the insn decoder. */
|
||||
if (cl_flags->flag_class & F_CLASS_IMPLICIT)
|
||||
{
|
||||
if (cl_flags->flag_class & F_CLASS_COND)
|
||||
arc_infop->condition_code = flg_operand->code;
|
||||
else if (cl_flags->flag_class & F_CLASS_WB)
|
||||
arc_infop->writeback_mode = flg_operand->code;
|
||||
else if (cl_flags->flag_class & F_CLASS_ZZ)
|
||||
info->data_size = flg_operand->code;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!flg_operand->favail)
|
||||
continue;
|
||||
|
||||
@ -496,8 +561,13 @@ print_flags (const struct arc_opcode *opcode,
|
||||
info->insn_type = dis_condjsr;
|
||||
else if (info->insn_type == dis_branch)
|
||||
info->insn_type = dis_condbranch;
|
||||
arc_infop->condition_code = flg_operand->code;
|
||||
}
|
||||
|
||||
/* Check for the write back modes. */
|
||||
if (cl_flags->flag_class & F_CLASS_WB)
|
||||
arc_infop->writeback_mode = flg_operand->code;
|
||||
|
||||
(*info->fprintf_func) (info->stream, "%s", flg_operand->name);
|
||||
}
|
||||
}
|
||||
@ -733,7 +803,15 @@ arc_opcode_to_insn_type (const struct arc_opcode *opcode)
|
||||
switch (opcode->insn_class)
|
||||
{
|
||||
case BRANCH:
|
||||
case BBIT0:
|
||||
case BBIT1:
|
||||
case BI:
|
||||
case BIH:
|
||||
case BRCC:
|
||||
case EI:
|
||||
case JLI:
|
||||
case JUMP:
|
||||
case LOOP:
|
||||
if (!strncmp (opcode->name, "bl", 2)
|
||||
|| !strncmp (opcode->name, "jl", 2))
|
||||
{
|
||||
@ -753,8 +831,14 @@ arc_opcode_to_insn_type (const struct arc_opcode *opcode)
|
||||
case LOAD:
|
||||
case STORE:
|
||||
case MEMORY:
|
||||
case ENTER:
|
||||
case PUSH:
|
||||
case POP:
|
||||
insn_type = dis_dref;
|
||||
break;
|
||||
case LEAVE:
|
||||
insn_type = dis_branch;
|
||||
break;
|
||||
default:
|
||||
insn_type = dis_nonbranch;
|
||||
break;
|
||||
@ -783,6 +867,7 @@ print_insn_arc (bfd_vma memaddr,
|
||||
int value;
|
||||
struct arc_operand_iterator iter;
|
||||
Elf_Internal_Ehdr *header = NULL;
|
||||
struct arc_disassemble_info *arc_infop;
|
||||
|
||||
if (info->disassembler_options)
|
||||
{
|
||||
@ -792,6 +877,9 @@ print_insn_arc (bfd_vma memaddr,
|
||||
info->disassembler_options = NULL;
|
||||
}
|
||||
|
||||
if (info->private_data == NULL && !init_arc_disasm_info (info))
|
||||
return -1;
|
||||
|
||||
memset (&iter, 0, sizeof (iter));
|
||||
highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
|
||||
lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
|
||||
@ -813,7 +901,7 @@ print_insn_arc (bfd_vma memaddr,
|
||||
default:
|
||||
isa_mask = ARC_OPCODE_ARCv2EM;
|
||||
/* TODO: Perhaps remove defitinion of header since it is only used at
|
||||
this location. */
|
||||
this location. */
|
||||
if (header != NULL
|
||||
&& (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
|
||||
{
|
||||
@ -899,6 +987,8 @@ print_insn_arc (bfd_vma memaddr,
|
||||
|
||||
insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
|
||||
pr_debug ("instruction length = %d bytes\n", insn_len);
|
||||
arc_infop = info->private_data;
|
||||
arc_infop->insn_len = insn_len;
|
||||
|
||||
switch (insn_len)
|
||||
{
|
||||
@ -957,7 +1047,7 @@ print_insn_arc (bfd_vma memaddr,
|
||||
/* Set some defaults for the insn info. */
|
||||
info->insn_info_valid = 1;
|
||||
info->branch_delay_insns = 0;
|
||||
info->data_size = 0;
|
||||
info->data_size = 4;
|
||||
info->insn_type = dis_nonbranch;
|
||||
info->target = 0;
|
||||
info->target2 = 0;
|
||||
@ -1016,6 +1106,7 @@ print_insn_arc (bfd_vma memaddr,
|
||||
|
||||
need_comma = FALSE;
|
||||
open_braket = FALSE;
|
||||
arc_infop->operands_count = 0;
|
||||
|
||||
/* Now extract and print the operands. */
|
||||
operand = NULL;
|
||||
@ -1034,14 +1125,14 @@ print_insn_arc (bfd_vma memaddr,
|
||||
|
||||
if ((operand->flags & ARC_OPERAND_IGNORE)
|
||||
&& (operand->flags & ARC_OPERAND_IR)
|
||||
&& value == -1)
|
||||
&& value == -1)
|
||||
continue;
|
||||
|
||||
if (operand->flags & ARC_OPERAND_COLON)
|
||||
{
|
||||
(*info->fprintf_func) (info->stream, ":");
|
||||
continue;
|
||||
}
|
||||
{
|
||||
(*info->fprintf_func) (info->stream, ":");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (need_comma)
|
||||
(*info->fprintf_func) (info->stream, ",");
|
||||
@ -1106,12 +1197,12 @@ print_insn_arc (bfd_vma memaddr,
|
||||
(*info->fprintf_func) (info->stream, "%d", value);
|
||||
}
|
||||
else if (operand->flags & ARC_OPERAND_ADDRTYPE)
|
||||
{
|
||||
const char *addrtype = get_addrtype (value);
|
||||
(*info->fprintf_func) (info->stream, "%s", addrtype);
|
||||
/* A colon follow an address type. */
|
||||
need_comma = FALSE;
|
||||
}
|
||||
{
|
||||
const char *addrtype = get_addrtype (value);
|
||||
(*info->fprintf_func) (info->stream, "%s", addrtype);
|
||||
/* A colon follow an address type. */
|
||||
need_comma = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (operand->flags & ARC_OPERAND_TRUNCATE
|
||||
@ -1129,6 +1220,24 @@ print_insn_arc (bfd_vma memaddr,
|
||||
(*info->fprintf_func) (info->stream, "%#x", value);
|
||||
}
|
||||
}
|
||||
|
||||
if (operand->flags & ARC_OPERAND_LIMM)
|
||||
{
|
||||
arc_infop->operands[arc_infop->operands_count].kind
|
||||
= ARC_OPERAND_KIND_LIMM;
|
||||
/* It is not important to have exactly the LIMM indicator
|
||||
here. */
|
||||
arc_infop->operands[arc_infop->operands_count].value = 63;
|
||||
}
|
||||
else
|
||||
{
|
||||
arc_infop->operands[arc_infop->operands_count].value = value;
|
||||
arc_infop->operands[arc_infop->operands_count].kind
|
||||
= (operand->flags & ARC_OPERAND_IR
|
||||
? ARC_OPERAND_KIND_REG
|
||||
: ARC_OPERAND_KIND_SHIMM);
|
||||
}
|
||||
arc_infop->operands_count ++;
|
||||
}
|
||||
|
||||
return insn_len;
|
||||
@ -1152,30 +1261,6 @@ arc_get_disassembler (bfd *abfd)
|
||||
return print_insn_arc;
|
||||
}
|
||||
|
||||
/* Disassemble ARC instructions. Used by debugger. */
|
||||
|
||||
struct arcDisState
|
||||
arcAnalyzeInstr (bfd_vma memaddr,
|
||||
struct disassemble_info *info)
|
||||
{
|
||||
struct arcDisState ret;
|
||||
memset (&ret, 0, sizeof (struct arcDisState));
|
||||
|
||||
ret.instructionLen = print_insn_arc (memaddr, info);
|
||||
|
||||
#if 0
|
||||
ret.words[0] = insn[0];
|
||||
ret.words[1] = insn[1];
|
||||
ret._this = &ret;
|
||||
ret.coreRegName = _coreRegName;
|
||||
ret.auxRegName = _auxRegName;
|
||||
ret.condCodeName = _condCodeName;
|
||||
ret.instName = _instName;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
print_arc_disassembler_options (FILE *stream)
|
||||
{
|
||||
@ -1199,6 +1284,58 @@ with -M switch (multiple options should be separated by commas):\n"));
|
||||
fpud Recognize double precision FPU instructions.\n"));
|
||||
}
|
||||
|
||||
void arc_insn_decode (bfd_vma addr,
|
||||
struct disassemble_info *info,
|
||||
disassembler_ftype disasm_func,
|
||||
struct arc_instruction *insn)
|
||||
{
|
||||
const struct arc_opcode *opcode;
|
||||
struct arc_disassemble_info *arc_infop;
|
||||
|
||||
/* Ensure that insn would be in the reset state. */
|
||||
memset (insn, 0, sizeof (struct arc_instruction));
|
||||
|
||||
/* There was an error when disassembling, for example memory read error. */
|
||||
if (disasm_func (addr, info) < 0)
|
||||
{
|
||||
insn->valid = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
assert (info->private_data != NULL);
|
||||
arc_infop = info->private_data;
|
||||
|
||||
insn->length = arc_infop->insn_len;;
|
||||
insn->address = addr;
|
||||
|
||||
/* Quick exit if memory at this address is not an instruction. */
|
||||
if (info->insn_type == dis_noninsn)
|
||||
{
|
||||
insn->valid = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
insn->valid = TRUE;
|
||||
|
||||
opcode = (const struct arc_opcode *) arc_infop->opcode;
|
||||
insn->insn_class = opcode->insn_class;
|
||||
insn->limm_value = arc_infop->limm;
|
||||
insn->limm_p = arc_infop->limm_p;
|
||||
|
||||
insn->is_control_flow = (info->insn_type == dis_branch
|
||||
|| info->insn_type == dis_condbranch
|
||||
|| info->insn_type == dis_jsr
|
||||
|| info->insn_type == dis_condjsr);
|
||||
|
||||
insn->has_delay_slot = info->branch_delay_insns;
|
||||
insn->writeback_mode
|
||||
= (enum arc_ldst_writeback_mode) arc_infop->writeback_mode;
|
||||
insn->data_size_mode = info->data_size;
|
||||
insn->condition_code = arc_infop->condition_code;
|
||||
memcpy (insn->operands, arc_infop->operands,
|
||||
sizeof (struct arc_insn_operand) * MAX_INSN_ARGS);
|
||||
insn->operands_count = arc_infop->operands_count;
|
||||
}
|
||||
|
||||
/* Local variables:
|
||||
eval: (c-set-style "gnu")
|
||||
|
@ -26,86 +26,148 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum ARC_Debugger_OperandType
|
||||
enum arc_ldst_writeback_mode
|
||||
{
|
||||
ARC_UNDEFINED,
|
||||
ARC_LIMM,
|
||||
ARC_SHIMM,
|
||||
ARC_REGISTER,
|
||||
ARCOMPACT_REGISTER /* Valid only for the
|
||||
registers allowed in
|
||||
16 bit mode. */
|
||||
ARC_WRITEBACK_NO = 0,
|
||||
ARC_WRITEBACK_AW = 1,
|
||||
ARC_WRITEBACK_A = ARC_WRITEBACK_AW,
|
||||
ARC_WRITEBACK_AB = 2,
|
||||
ARC_WRITEBACK_AS = 3,
|
||||
};
|
||||
|
||||
enum Flow
|
||||
|
||||
enum arc_ldst_data_size
|
||||
{
|
||||
noflow,
|
||||
direct_jump,
|
||||
direct_call,
|
||||
indirect_jump,
|
||||
indirect_call,
|
||||
invalid_instr
|
||||
ARC_SCALING_NONE = 4,
|
||||
ARC_SCALING_B = 1,
|
||||
ARC_SCALING_H = 2,
|
||||
ARC_SCALING_D = 8,
|
||||
};
|
||||
|
||||
enum NullifyMode
|
||||
|
||||
enum arc_condition_code
|
||||
{
|
||||
BR_exec_when_no_jump,
|
||||
BR_exec_always,
|
||||
BR_exec_when_jump
|
||||
ARC_CC_AL = 0x0,
|
||||
ARC_CC_RA = ARC_CC_AL,
|
||||
ARC_CC_EQ = 0x1,
|
||||
ARC_CC_Z = ARC_CC_EQ,
|
||||
ARC_CC_NE = 0x2,
|
||||
ARC_CC_NZ = ARC_CC_NE,
|
||||
ARC_CC_PL = 0x3,
|
||||
ARC_CC_P = ARC_CC_PL,
|
||||
ARC_CC_MI = 0x4,
|
||||
ARC_CC_N = ARC_CC_MI,
|
||||
ARC_CC_CS = 0x5,
|
||||
ARC_CC_C = ARC_CC_CS,
|
||||
ARC_CC_LO = ARC_CC_CS,
|
||||
ARC_CC_CC = 0x6,
|
||||
ARC_CC_NC = ARC_CC_CC,
|
||||
ARC_CC_HS = ARC_CC_CC,
|
||||
ARC_CC_VS = 0x7,
|
||||
ARC_CC_V = ARC_CC_VS,
|
||||
ARC_CC_VC = 0x8,
|
||||
ARC_CC_NV = ARC_CC_VC,
|
||||
ARC_CC_GT = 0x9,
|
||||
ARC_CC_GE = 0xA,
|
||||
ARC_CC_LT = 0xB,
|
||||
ARC_CC_LE = 0xC,
|
||||
ARC_CC_HI = 0xD,
|
||||
ARC_CC_LS = 0xE,
|
||||
ARC_CC_PNZ = 0xF,
|
||||
ARC_CC_UNDEF0 = 0x10,
|
||||
ARC_CC_UNDEF1 = 0x11,
|
||||
ARC_CC_UNDEF2 = 0x12,
|
||||
ARC_CC_UNDEF3 = 0x13,
|
||||
ARC_CC_UNDEF4 = 0x14,
|
||||
ARC_CC_UNDEF5 = 0x15,
|
||||
ARC_CC_UNDEF6 = 0x16,
|
||||
ARC_CC_UNDEF7 = 0x17,
|
||||
ARC_CC_UNDEF8 = 0x18,
|
||||
ARC_CC_UNDEF9 = 0x19,
|
||||
ARC_CC_UNDEFA = 0x1A,
|
||||
ARC_CC_UNDEFB = 0x1B,
|
||||
ARC_CC_UNDEFC = 0x1C,
|
||||
ARC_CC_UNDEFD = 0x1D,
|
||||
ARC_CC_UNDEFE = 0x1E,
|
||||
ARC_CC_UNDEFF = 0x1F
|
||||
};
|
||||
|
||||
enum { allOperandsSize = 256 };
|
||||
|
||||
struct arcDisState
|
||||
enum arc_operand_kind
|
||||
{
|
||||
void *_this;
|
||||
int instructionLen;
|
||||
void (*err)(void*, const char*);
|
||||
const char *(*coreRegName)(void*, int);
|
||||
const char *(*auxRegName)(void*, int);
|
||||
const char *(*condCodeName)(void*, int);
|
||||
const char *(*instName)(void*, int, int, int*);
|
||||
|
||||
unsigned char* instruction;
|
||||
unsigned index;
|
||||
const char *comm[6]; /* Instr name, cond, NOP, 3 operands. */
|
||||
|
||||
union
|
||||
{
|
||||
unsigned int registerNum;
|
||||
unsigned int shortimm;
|
||||
unsigned int longimm;
|
||||
} source_operand;
|
||||
enum ARC_Debugger_OperandType sourceType;
|
||||
|
||||
int opWidth;
|
||||
int targets[4];
|
||||
/* START ARC LOCAL. */
|
||||
unsigned int addresses[4];
|
||||
/* END ARC LOCAL. */
|
||||
/* Set as a side-effect of calling the disassembler.
|
||||
Used only by the debugger. */
|
||||
enum Flow flow;
|
||||
int register_for_indirect_jump;
|
||||
int ea_reg1, ea_reg2, _offset;
|
||||
int _cond, _opcode;
|
||||
unsigned long words[2];
|
||||
char *commentBuffer;
|
||||
char instrBuffer[40];
|
||||
char operandBuffer[allOperandsSize];
|
||||
char _ea_present;
|
||||
char _addrWriteBack; /* Address writeback. */
|
||||
char _mem_load;
|
||||
char _load_len;
|
||||
enum NullifyMode nullifyMode;
|
||||
unsigned char commNum;
|
||||
unsigned char isBranch;
|
||||
unsigned char tcnt;
|
||||
unsigned char acnt;
|
||||
ARC_OPERAND_KIND_UNKNOWN = 0,
|
||||
ARC_OPERAND_KIND_REG,
|
||||
ARC_OPERAND_KIND_SHIMM,
|
||||
ARC_OPERAND_KIND_LIMM
|
||||
};
|
||||
|
||||
struct arcDisState
|
||||
arcAnalyzeInstr (bfd_vma memaddr, struct disassemble_info *);
|
||||
struct arc_insn_operand
|
||||
{
|
||||
/* Operand value as encoded in instruction. */
|
||||
unsigned long value;
|
||||
|
||||
enum arc_operand_kind kind;
|
||||
};
|
||||
|
||||
/* Container for information about instruction. Provides a higher
|
||||
level access to data that is contained in struct arc_opcode. */
|
||||
|
||||
struct arc_instruction
|
||||
{
|
||||
/* Address of this instruction. */
|
||||
bfd_vma address;
|
||||
|
||||
/* Whether this is a valid instruction. */
|
||||
bfd_boolean valid;
|
||||
|
||||
insn_class_t insn_class;
|
||||
|
||||
/* Length (without LIMM). */
|
||||
unsigned length;
|
||||
|
||||
/* Is there a LIMM in this instruction? */
|
||||
int limm_p;
|
||||
|
||||
/* Long immediate value. */
|
||||
unsigned limm_value;
|
||||
|
||||
/* Is it a branch/jump instruction? */
|
||||
int is_control_flow;
|
||||
|
||||
/* Whether this instruction has a delay slot. */
|
||||
int has_delay_slot;
|
||||
|
||||
/* Value of condition code field. */
|
||||
enum arc_condition_code condition_code;
|
||||
|
||||
/* Load/store writeback mode. */
|
||||
enum arc_ldst_writeback_mode writeback_mode;
|
||||
|
||||
/* Load/store data size. */
|
||||
enum arc_ldst_data_size data_size_mode;
|
||||
|
||||
/* Amount of operands in instruction. Note that amount of operands
|
||||
reported by opcodes disassembler can be different from the one
|
||||
encoded in the instruction. Notable case is "ld a,[b,offset]",
|
||||
when offset == 0. In this case opcodes disassembler presents
|
||||
this instruction as "ld a,[b]", hence there are *two* operands,
|
||||
not three. OPERANDS_COUNT and OPERANDS contain only those
|
||||
explicit operands, hence it is up to invoker to handle the case
|
||||
described above based on instruction opcodes. Another notable
|
||||
thing is that in opcodes disassembler representation square
|
||||
brackets (`[' and `]') are so called fake-operands - they are in
|
||||
the list of operands, but do not have any value of they own.
|
||||
Those "operands" are not present in this array. */
|
||||
struct arc_insn_operand operands[MAX_INSN_ARGS];
|
||||
|
||||
unsigned int operands_count;
|
||||
};
|
||||
|
||||
/* Fill INSN with data about instruction at specified ADDR. */
|
||||
|
||||
void arc_insn_decode (bfd_vma addr,
|
||||
struct disassemble_info *di,
|
||||
disassembler_ftype func,
|
||||
struct arc_instruction *insn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1290,9 +1290,11 @@ const struct arc_flag_operand arc_flag_operands[] =
|
||||
{ "h", 2, 2, 7, 1 },
|
||||
#define F_H17 (F_H7 + 1)
|
||||
{ "h", 2, 2, 17, 1 },
|
||||
#define F_SIZED (F_H17 + 1)
|
||||
{ "dd", 8, 0, 0, 0 }, /* Fake. */
|
||||
|
||||
/* Fake Flags. */
|
||||
#define F_NE (F_H17 + 1)
|
||||
#define F_NE (F_SIZED + 1)
|
||||
{ "ne", 0, 0, 0, 1 },
|
||||
|
||||
/* ARC NPS400 Support: See comment near head of file. */
|
||||
@ -1398,7 +1400,52 @@ const struct arc_flag_class arc_flag_classes[] =
|
||||
#define C_EMPTY 0
|
||||
{ F_CLASS_NONE, { F_NULL } },
|
||||
|
||||
#define C_CC (C_EMPTY + 1)
|
||||
#define C_CC_EQ (C_EMPTY + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_EQUAL, F_NULL} },
|
||||
|
||||
#define C_CC_GE (C_CC_EQ + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_GE, F_NULL} },
|
||||
|
||||
#define C_CC_GT (C_CC_GE + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_GT, F_NULL} },
|
||||
|
||||
#define C_CC_HI (C_CC_GT + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_HI, F_NULL} },
|
||||
|
||||
#define C_CC_HS (C_CC_HI + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_NOTCARRY, F_NULL} },
|
||||
|
||||
#define C_CC_LE (C_CC_HS + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_LE, F_NULL} },
|
||||
|
||||
#define C_CC_LO (C_CC_LE + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_CARRY, F_NULL} },
|
||||
|
||||
#define C_CC_LS (C_CC_LO + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_LS, F_NULL} },
|
||||
|
||||
#define C_CC_LT (C_CC_LS + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_LT, F_NULL} },
|
||||
|
||||
#define C_CC_NE (C_CC_LT + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_COND, {F_NOTEQUAL, F_NULL} },
|
||||
|
||||
#define C_AA_AB (C_CC_NE + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_WB, {F_AB3, F_NULL} },
|
||||
|
||||
#define C_AA_AW (C_AA_AB + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_WB, {F_AW3, F_NULL} },
|
||||
|
||||
#define C_ZZ_D (C_AA_AW + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_ZZ, {F_SIZED, F_NULL} },
|
||||
|
||||
#define C_ZZ_H (C_ZZ_D + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_ZZ, {F_H1, F_NULL} },
|
||||
|
||||
#define C_ZZ_B (C_ZZ_H + 1)
|
||||
{F_CLASS_IMPLICIT | F_CLASS_ZZ, {F_SIZEB1, F_NULL} },
|
||||
|
||||
#define C_CC (C_ZZ_B + 1)
|
||||
{ F_CLASS_OPTIONAL | F_CLASS_EXTEND | F_CLASS_COND,
|
||||
{ F_ALWAYS, F_RA, F_EQUAL, F_ZERO, F_NOTEQUAL,
|
||||
F_NOTZERO, F_POZITIVE, F_PL, F_NEGATIVE, F_MINUS,
|
||||
@ -1409,13 +1456,13 @@ const struct arc_flag_class arc_flag_classes[] =
|
||||
|
||||
#define C_AA_ADDR3 (C_CC + 1)
|
||||
#define C_AA27 (C_CC + 1)
|
||||
{ F_CLASS_OPTIONAL, { F_A3, F_AW3, F_AB3, F_AS3, F_NULL } },
|
||||
{ F_CLASS_OPTIONAL | F_CLASS_WB, { F_A3, F_AW3, F_AB3, F_AS3, F_NULL } },
|
||||
#define C_AA_ADDR9 (C_AA_ADDR3 + 1)
|
||||
#define C_AA21 (C_AA_ADDR3 + 1)
|
||||
{ F_CLASS_OPTIONAL, { F_A9, F_AW9, F_AB9, F_AS9, F_NULL } },
|
||||
{ F_CLASS_OPTIONAL | F_CLASS_WB, { F_A9, F_AW9, F_AB9, F_AS9, F_NULL } },
|
||||
#define C_AA_ADDR22 (C_AA_ADDR9 + 1)
|
||||
#define C_AA8 (C_AA_ADDR9 + 1)
|
||||
{ F_CLASS_OPTIONAL, { F_A22, F_AW22, F_AB22, F_AS22, F_NULL } },
|
||||
{ F_CLASS_OPTIONAL | F_CLASS_WB, { F_A22, F_AW22, F_AB22, F_AS22, F_NULL } },
|
||||
|
||||
#define C_F (C_AA_ADDR22 + 1)
|
||||
{ F_CLASS_OPTIONAL, { F_FLAG, F_NULL } },
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user