summaryrefslogtreecommitdiff
path: root/opcodes/arcompact-dis.c
diff options
context:
space:
mode:
authorJoern Rennecke <joern.rennecke@embecosm.com>2009-03-09 21:10:29 +0000
committerJoern Rennecke <joern.rennecke@embecosm.com>2009-03-09 21:10:29 +0000
commit4195238713fd818958a9e41fee154ea357304b59 (patch)
treef0447c9c95b1b02ecb09ee326d2de6934c6dcdaa /opcodes/arcompact-dis.c
parentfa7f0c2d4e8e670a608337d71857408010551215 (diff)
downloadbinutils-gdb-4195238713fd818958a9e41fee154ea357304b59.tar.gz
Check in ARCompact simulator. A valid configuration is arc-elf.arc-sim-20090309
This is not quite finished and has most likely a few files that are obsolete & not used, but it's good enough to run gcc regression tests.
Diffstat (limited to 'opcodes/arcompact-dis.c')
-rw-r--r--opcodes/arcompact-dis.c3833
1 files changed, 3833 insertions, 0 deletions
diff --git a/opcodes/arcompact-dis.c b/opcodes/arcompact-dis.c
new file mode 100644
index 00000000000..545eecbf30b
--- /dev/null
+++ b/opcodes/arcompact-dis.c
@@ -0,0 +1,3833 @@
+/* Instruction printing code for the ARC.
+ Copyright (C) 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
+ Contributed by Doug Evans (dje@cygnus.com).
+
+ Sources derived from work done by Sankhya Technologies (www.sankhya.com)
+
+ Cleaned up , Comments Added, Support For A700 instructions by
+ Saurabh Verma (saurabh.verma@codito.com)
+ Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include <ansidecl.h>
+#include "dis-asm.h"
+#include "opcode/arc.h"
+#include "elf-bfd.h"
+#include "elf/arc.h"
+#include <string.h>
+
+#include <ctype.h>
+#include <stdarg.h>
+#include "arc-dis.h"
+#include "arc-ext.h"
+
+ /*
+ warning: implicit declaration of function `printf_unfiltered'
+ if dbg is 1 then this definition is required
+ */
+ void printf_unfiltered (const char *,...);
+static bfd_vma bfd_getm32 (unsigned int);
+static bfd_vma bfd_getm32_ac (unsigned int) ATTRIBUTE_UNUSED;
+struct arcDisState arcAnalyzeInstr (bfd_vma, disassemble_info*);
+
+
+#ifndef dbg
+#define dbg (0)
+#endif
+
+ /*
+ Ravi:
+ : undefined reference to `printf_unfiltered'
+ if dbg is 1 then this definition is required
+ */
+#if dbg
+ void printf_unfiltered (const char *,...)
+ {
+ va_list args;
+ va_start (args, format);
+ vfprintf_unfiltered (gdb_stdout, format, args);
+ va_end (args);
+ }
+#endif
+
+#undef _NELEM
+#define _NELEM(ary) (sizeof(ary) / sizeof(ary[0]))
+
+#define BIT(word,n) ((word) & (1 << n))
+#define BITS(word,s,e) (((word) << (31-e)) >> (s+(31-e)))
+#define OPCODE(word) (BITS ((word), 27, 31))
+#define FIELDA(word) (BITS ((word), 0, 5))
+#define FIELDb(word) (BITS ((word), 24, 26))
+#define FIELDB(word) (BITS ((word), 12, 14))
+#define FIELDC(word) (BITS ((word), 6, 11))
+#define OPCODE_AC(word) (BITS ((word), 11, 15))
+#define FIELDA_AC(word) (BITS ((word), 0, 2))
+#define FIELDB_AC(word) (BITS ((word), 8, 10))
+#define FIELDC_AC(word) (BITS ((word), 5, 7))
+#define FIELDU_AC(word) (BITS ((word), 0, 4))
+
+/*
+ * FIELDS_AC is the 11-bit signed immediate value used for
+ * GP-relative instructions.
+ */
+#define FIELDS_AC(word) (BITS (((signed int) word), 0, 8))
+
+/*
+ * FIELDD is signed in all of its uses, so we make sure argument is
+ * treated as signed for bit shifting purposes.
+ */
+#define FIELDD(word) (BITS (((signed int) word), 16, 23))
+
+/*
+ * FIELDD9 is the 9-bit signed immediate value used for
+ * load/store instructions.
+ */
+#define FIELDD9(word) ((BITS(((signed int)word),15,15) << 8) | (BITS((word),16,23)))
+
+/*
+ * FIELDS is the 12-bit signed immediate value
+ */
+#define FIELDS(word) ((BITS(((signed int)word),0,5) << 6) | (BITS((word),6,11))) \
+
+/*
+ * FIELD S9 is the 9-bit signed immediate value used for
+ * bbit0/bbit instruction
+ */
+#define FIELDS9(word) (((BITS(((signed int)word),15,15) << 7) | (BITS((word),17,23))) << 1)
+#define FIELDS9_FLAG(word) (((BITS(((signed int)word),0,5) << 6) | (BITS((word),6,11))) )
+
+#define PUT_NEXT_WORD_IN(a) { \
+ if (is_limm==1 && !NEXT_WORD(1)) \
+ mwerror(state, "Illegal limm reference in last instruction!\n"); \
+ a = ((state->words[1] & 0xff00) | (state->words[1] & 0xff)) << 16; \
+ a |= ((state->words[1] & 0xff0000) | (state->words[1] & 0xff000000)) >> 16; \
+ }
+
+#define CHECK_NULLIFY() do{ \
+ state->nullifyMode = BITS(state->words[0],5,5); \
+ }while(0)
+
+#define CHECK_COND_NULLIFY() do { \
+ state->nullifyMode = BITS(state->words[0],5,5); \
+ cond = BITS(state->words[0],0,4); \
+ }while(0)
+
+#define CHECK_FLAG_COND_NULLIFY() do{ \
+ if (is_shimm == 0) { \
+ flag = BIT(state->words[0],15); \
+ state->nullifyMode = BITS(state->words[0],5,5); \
+ cond = BITS(state->words[0],0,4); \
+ } \
+ }while(0)
+
+#define CHECK_FLAG_COND() { \
+ if (is_shimm == 0) { \
+ flag = BIT(state->words[0],15); \
+ cond = BITS(state->words[0],0,4); \
+ } \
+ }
+
+#define CHECK_FLAG() { \
+ flag = BIT(state->words[0],15); \
+ }
+
+#define CHECK_COND() { \
+ if (is_shimm == 0) { \
+ cond = BITS(state->words[0],0,4); \
+ } \
+ }
+
+#define CHECK_FIELD(field) { \
+ if (field == 62) { \
+ is_limm++; \
+ field##isReg = 0; \
+ PUT_NEXT_WORD_IN(field); \
+ limm_value = field; \
+ } \
+ }
+
+#define CHECK_FIELD_A() { \
+ fieldA = FIELDA(state->words[0]); \
+ if (fieldA == 62) { \
+ fieldAisReg = 0; \
+ fieldA = 0; \
+ } \
+ }
+
+#define FIELD_B() { \
+ fieldB = (FIELDB(state->words[0]) << 3);\
+ fieldB |= FIELDb(state->words[0]); \
+ if (fieldB == 62) { \
+ fieldBisReg = 0; \
+ fieldB = 0; \
+ } \
+ }
+
+#define FIELD_C() { \
+ fieldC = FIELDC(state->words[0]); \
+ if (fieldC == 62) { \
+ fieldCisReg = 0; \
+ } \
+ }
+/********** Aurora SIMD ARC 8 - bit constant **********/
+#define FIELD_U8() { \
+ \
+ fieldC = BITS(state->words[0],15,16);\
+ fieldC = fieldC <<6; \
+ fieldC |= FIELDC(state->words[0]); \
+ fieldCisReg = 0; \
+ }
+
+#define CHECK_FIELD_B() { \
+ fieldB = (FIELDB(state->words[0]) << 3);\
+ fieldB |= FIELDb(state->words[0]); \
+ CHECK_FIELD(fieldB); \
+ }
+
+#define CHECK_FIELD_C() { \
+ fieldC = FIELDC(state->words[0]); \
+ CHECK_FIELD(fieldC); \
+ }
+
+#define FIELD_C_S() { \
+ fieldC_S = (FIELDC_S(state->words[0]) << 3); \
+ }
+
+#define FIELD_B_S() { \
+ fieldB_S = (FIELDB_S(state->words[0]) << 3); \
+ }
+
+#define CHECK_FIELD_H_AC() { \
+ fieldC = ((FIELDA_AC(state->words[0])) << 3); \
+ fieldC |= FIELDC_AC(state->words[0]); \
+ CHECK_FIELD(fieldC); \
+ }
+
+#define FIELD_H_AC() { \
+ fieldC = ((FIELDA_AC(state->words[0])) << 3); \
+ fieldC |= FIELDC_AC(state->words[0]); \
+ if (fieldC > 60) { \
+ fieldCisReg = 0; \
+ fieldC = 0; \
+ } \
+ }
+
+#define FIELD_C_AC() { \
+ fieldC = FIELDC_AC(state->words[0]); \
+ if (fieldC > 3) { \
+ fieldC += 8; \
+ } \
+ }
+
+#define FIELD_B_AC() { \
+ fieldB = FIELDB_AC(state->words[0]); \
+ if (fieldB > 3) { \
+ fieldB += 8; \
+ } \
+ }
+
+#define FIELD_A_AC() { \
+ fieldA = FIELDA_AC(state->words[0]); \
+ if (fieldA > 3) { \
+ fieldA += 8; \
+ } \
+ }
+
+#define IS_SMALL(x) (((field##x) < 256) && ((field##x) > -257))
+#define IS_REG(x) (field##x##isReg)
+#define IS_SIMD_128_REG(x) (usesSimdReg##x == 1)
+#define IS_SIMD_16_REG(x) (usesSimdReg##x == 2)
+#define IS_SIMD_DATA_REG(x) (usesSimdReg##x == 3)
+#define WRITE_FORMAT_LB_Rx_RB(x) WRITE_FORMAT(x,"[","]","","")
+#define WRITE_FORMAT_x_COMMA_LB(x) WRITE_FORMAT(x,"",",[","",",[")
+#define WRITE_FORMAT_COMMA_x_RB(x) WRITE_FORMAT(x,",","]",",","]")
+#define WRITE_FORMAT_x_RB(x) WRITE_FORMAT(x,"","]","","]")
+#define WRITE_FORMAT_COMMA_x(x) WRITE_FORMAT(x,",","",",","")
+#define WRITE_FORMAT_x_COMMA(x) WRITE_FORMAT(x,"",",","",",")
+#define WRITE_FORMAT_x(x) WRITE_FORMAT(x,"","","","")
+#define WRITE_FORMAT(x,cb1,ca1,cb,ca) strcat(formatString, \
+ (IS_SIMD_128_REG(x) ? cb1"%S"ca1: \
+ IS_SIMD_16_REG(x) ? cb1"%I"ca1: \
+ IS_SIMD_DATA_REG(x)? cb1"%D"ca1: \
+ IS_REG(x) ? cb1"%r"ca1: \
+ usesAuxReg ? cb"%a"ca : \
+ IS_SMALL(x) ? cb"%d"ca : cb"%h"ca))
+
+#define WRITE_FORMAT_LB() strcat(formatString, "[")
+#define WRITE_FORMAT_RB() strcat(formatString, "]")
+#define WRITE_COMMENT(str) (state->comm[state->commNum++] = (str))
+#define WRITE_NOP_COMMENT() if (!fieldAisReg && !flag) WRITE_COMMENT("nop");
+
+#define NEXT_WORD(x) (offset += 4, state->words[x])
+
+#define NEXT_WORD_AC(x) (offset += 2, state->words[x])
+
+#define add_target(x) (state->targets[state->tcnt++] = (x))
+
+static char comment_prefix[] = "\t; ";
+short int enable_simd = 0;
+
+static const char *
+core_reg_name(struct arcDisState *state, int val)
+{
+ if (state->coreRegName)
+ return (*state->coreRegName)(state->_this, val);
+ return 0;
+}
+
+static const char *
+aux_reg_name(struct arcDisState *state, int val)
+{
+ if (state->auxRegName)
+ return (*state->auxRegName)(state->_this, val);
+ return 0;
+}
+
+static const char *
+cond_code_name(struct arcDisState *state, int val)
+{
+ if (state->condCodeName)
+ return (*state->condCodeName)(state->_this, val);
+ return 0;
+}
+
+static const char *
+instruction_name(struct arcDisState *state, int op1, int op2, int *flags)
+{
+ if (state->instName)
+ return (*state->instName)(state->_this, op1, op2, flags);
+ return 0;
+}
+
+static void
+mwerror(struct arcDisState *state, const char *msg)
+{
+ if (state->err != 0)
+ (*state->err)(state->_this, (msg));
+}
+
+static const char *
+post_address(struct arcDisState *state, int addr)
+{
+ static char id[3*_NELEM(state->addresses)];
+ unsigned int j, i = state->acnt;
+ if (i < _NELEM(state->addresses)) {
+ state->addresses[i] = addr;
+ ++state->acnt;
+ j = i*3;
+ id[j+0] = '@';
+ id[j+1] = '0'+i;
+ id[j+2] = 0;
+ return id+j;
+ }
+ return "";
+}
+
+static void
+my_sprintf (struct arcDisState *state, char *buf, const char*format, ...)
+{
+ char *bp;
+ const char *p;
+ int size, leading_zero, regMap[2];
+ long auxNum;
+ va_list ap;
+
+ va_start(ap,format);
+ bp = buf;
+ *bp = 0;
+ p = format;
+ auxNum = -1;
+ regMap[0] = 0;
+ regMap[1] = 0;
+ while (1)
+ switch(*p++) {
+ case 0: goto DOCOMM; /*(return) */
+ default:
+ *bp++ = p[-1];
+ break;
+ case '%':
+ size = 0;
+ leading_zero = 0;
+ RETRY: ;
+ switch(*p++)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ /* size. */
+ size = p[-1]-'0';
+ if (size == 0) leading_zero = 1; /* e.g. %08x */
+ while (*p >= '0' && *p <= '9')
+ size = size*10+*p-'0', p++;
+ goto RETRY;
+ }
+#define inc_bp() bp = bp+strlen(bp)
+
+ case 'h':
+ {
+ unsigned u = va_arg(ap,int);
+ /*
+ * Hex. We can change the format to 0x%08x in
+ * one place, here, if we wish.
+ * We add underscores for easy reading.
+ */
+#define CDT_DEBUG
+ if (u > 65536)
+#ifndef CDT_DEBUG
+ sprintf(bp,"0x%x_%04x",u >> 16, u & 0xffff);
+#else
+ sprintf(bp,"0x%08x",u);
+#endif // CDT_DEBUG
+ else
+ sprintf(bp,"0x%x",u);
+ inc_bp();
+ }
+ break;
+ case 'X': case 'x':
+ {
+ int val = va_arg(ap,int);
+ if (size != 0)
+ if (leading_zero) sprintf(bp,"%0*x",size,val);
+ else sprintf(bp,"%*x",size,val);
+ else sprintf(bp,"%x",val);
+ inc_bp();
+ }
+ break;
+ case 'd':
+ {
+ int val = va_arg(ap,int);
+ if (size != 0) sprintf(bp,"%*d",size,val);
+ else sprintf(bp,"%d",val);
+ inc_bp();
+ }
+ break;
+ case 'r':
+ {
+ /* Register. */
+ int val = va_arg(ap,int);
+
+#define REG2NAME(num, name) case num: sprintf(bp,""name); \
+ regMap[(num<32)?0:1] |= 1<<(num-((num<32)?0:32)); break;
+ switch (val)
+ {
+ REG2NAME(26, "gp");
+ REG2NAME(27, "fp");
+ REG2NAME(28, "sp");
+ REG2NAME(29, "ilink1");
+ REG2NAME(30, "ilink2");
+ REG2NAME(31, "blink");
+ REG2NAME(60, "lp_count");
+ REG2NAME(63, "pcl");
+ default:
+ {
+ const char *ext;
+ ext = core_reg_name(state, val);
+ if (ext) sprintf(bp, "%s", ext);
+ else sprintf(bp,"r%d",val);
+ }break;
+ }
+ inc_bp();
+ } break;
+
+ case 'a':
+ {
+ /* Aux Register. */
+ int val = va_arg(ap,int);
+ char *ret;
+ ret = arc_aux_reg_name(val);
+ if(ret)
+ sprintf(bp,"%s",ret);
+ else
+ {
+ const char *ext;
+ ext = aux_reg_name(state, val);
+ if (ext) sprintf(bp, "%s", ext);
+ else my_sprintf(state, bp,"%h",val);
+ }
+
+ inc_bp();
+ }
+ break;
+ case 's':
+ {
+ sprintf(bp,"%s",va_arg(ap,char*));
+ inc_bp();
+ }
+ break;
+ case '*':
+ {
+ va_arg(ap,char*);
+ inc_bp();
+ break;
+ }
+
+ /* SIMD operands follow*/
+ case 'S':
+ {
+ int val = va_arg (ap,int);
+
+ sprintf (bp, "vr%d",val);
+ inc_bp ();
+ break;
+ }
+ case 'I':
+ {
+ int val = va_arg (ap,int);
+
+ sprintf (bp, "i%d",val);
+ inc_bp ();
+ break;
+ }
+ case 'D':
+ {
+ int val = va_arg (ap,int);
+
+ sprintf (bp, "dr%d",val);
+ inc_bp ();
+ break;
+ }
+ /* SIMD operands end */
+ default:
+ fprintf(stderr,"?? format %c\n",p[-1]);
+ break;
+ }
+ }
+
+
+ DOCOMM: *bp = 0;
+
+}
+
+static void
+write_comments_(struct arcDisState *state, int shimm, int is_limm, long limm_value)
+{
+ if (state->commentBuffer != 0)
+ {
+ int i;
+ if (is_limm)
+ {
+ const char *name = post_address(state, limm_value+shimm);
+ if (*name != 0) WRITE_COMMENT(name);
+ }
+ for(i = 0; i < state->commNum; i++)
+ {
+ if (i == 0) strcpy(state->commentBuffer, comment_prefix);
+ else strcat(state->commentBuffer, ", ");
+ strncat(state->commentBuffer, state->comm[i], sizeof(state->commentBuffer));
+ }
+ }
+}
+
+#define write_comments2(x) write_comments_(state, x, is_limm, limm_value)
+#define write_comments() write_comments2(0)
+
+static const char *condName[] =
+{
+ /* 0..15. */
+ "" , "z" , "nz" , "p" , "n" , "c" , "nc" , "v" ,
+ "nv" , "gt" , "ge" , "lt" , "le" , "hi" , "ls" , "pnz",
+ "ss" , "sc"
+
+};
+
+static void
+write_instr_name_(struct arcDisState *state,
+ const char *instrName,
+ int cond,
+ int condCodeIsPartOfName,
+ int flag,
+ int signExtend,
+ int addrWriteBack,
+ int directMem)
+{
+ strcpy(state->instrBuffer, instrName);
+ if (cond > 0)
+ {
+ int condlim = 0; /* condition code limit*/
+ const char *cc = 0;
+ if (!condCodeIsPartOfName) strcat(state->instrBuffer, ".");
+ condlim = 18;
+ if (cond < condlim)
+ cc = condName[cond];
+ else
+ cc = cond_code_name(state, cond);
+ if (!cc) cc = "???";
+ strcat(state->instrBuffer, cc);
+ }
+ if (flag) strcat(state->instrBuffer, ".f");
+ if (state->nullifyMode)
+ strcat(state->instrBuffer, ".d");
+ if (signExtend) strcat(state->instrBuffer, ".x");
+ switch (addrWriteBack)
+ {
+ case 1: strcat(state->instrBuffer, ".a"); break;
+ case 2: strcat(state->instrBuffer, ".ab"); break;
+ case 3: strcat(state->instrBuffer, ".as"); break;
+ }
+ if (directMem) strcat(state->instrBuffer, ".di");
+}
+
+#define write_instr_name() {\
+ write_instr_name_(state, instrName,cond, condCodeIsPartOfName, flag, signExtend, addrWriteBack, directMem); \
+ formatString[0] = '\0'; \
+}
+
+enum
+{
+ op_BC = 0, op_BLC = 1, op_LD = 2, op_ST = 3, op_MAJOR_4 = 4,
+ op_MAJOR_5 = 5, op_SIMD=6, op_LD_ADD = 12, op_ADD_SUB_SHIFT = 13,
+ op_ADD_MOV_CMP = 14, op_S = 15, op_LD_S = 16, op_LDB_S = 17,
+ op_LDW_S = 18, op_LDWX_S = 19, op_ST_S = 20, op_STB_S = 21,
+ op_STW_S = 22, op_Su5 = 23, op_SP = 24, op_GP = 25, op_Pcl = 26,
+ op_MOV_S = 27, op_ADD_CMP = 28, op_BR_S = 29, op_B_S = 30, op_BL_S = 31
+};
+
+extern disassemble_info tm_print_insn_info;
+
+/*
+ * bfd_getm32 - To retrieve the upper 16-bits of the ARCtangent-A5
+ * basecase (32-bit) instruction
+ */
+static bfd_vma
+bfd_getm32 (data)
+ unsigned int data;
+{
+ bfd_vma value = 0;
+
+ value = ((data & 0xff00) | (data & 0xff)) << 16;
+ value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
+ return value;
+}
+
+/*
+ * bfd_getm32_ac - To retrieve the upper 8-bits of the ARCompact
+ * 16-bit instruction
+ */
+static bfd_vma
+bfd_getm32_ac (data)
+ unsigned int data;
+{
+ bfd_vma value = 0;
+
+ value = ((data & 0xff) << 8 | (data & 0xff00) >> 8);
+ return value;
+}
+
+/*
+ * sign_extend - Sign Extend the value
+ *
+ */
+static int
+sign_extend (int value, int bits)
+{
+ if (BIT(value, (bits-1)))
+ value |= (0xffffffff << bits);
+ return value;
+}
+
+/* dsmOneArcInst - This module is used to identify the instruction
+ * and to decode them based on the ARCtangent-A5
+ * instruction set architecture.
+ * First, the major opcode is computed. Based on the
+ * major opcode and sub opcode, the instruction is
+ * identified. The appropriate decoding class is assigned
+ * based on the instruction.Further subopcode 2 is used in
+ * cases where decoding upto subopcode1 is not possible.
+ *
+ * The instruction is then decoded accordingly.
+ */
+static int
+dsmOneArcInst (bfd_vma addr, struct arcDisState *state, disassemble_info * info)
+{
+
+ int subopcode, mul;
+ int condCodeIsPartOfName=0;
+ int decodingClass;
+ const char *instrName;
+ int fieldAisReg=1, fieldBisReg=1, fieldCisReg=1;
+ int fieldA=0, fieldB=0, fieldC=0;
+ int flag=0, cond=0, is_shimm=0, is_limm=0;
+ long limm_value=0;
+ int signExtend=0, addrWriteBack=0, directMem=0;
+ int is_linked=0;
+ int offset=0;
+ int usesAuxReg = 0;
+ int usesSimdRegA= 0, usesSimdRegB=0, usesSimdRegC=0,simd_scale_u8=-1;
+ int flags = !E_ARC_MACH_A4;
+ char formatString[60];
+
+ state->nullifyMode = BR_exec_when_no_jump;
+ state->isBranch = 0;
+
+ state->_mem_load = 0;
+ state->_ea_present = 0;
+ state->_load_len = 0;
+ state->ea_reg1 = no_reg;
+ state->ea_reg2 = no_reg;
+ state->_offset = 0;
+ state->_addrWriteBack = 0;
+
+ state->instructionLen = info->bytes_per_line;
+
+ /* ARCtangent-A5 basecase instruction and little-endian mode */
+ if ((info->endian == BFD_ENDIAN_LITTLE) && (state->instructionLen == 4))
+ state->words[0] = bfd_getm32(state->words[0]);
+
+ if (state->instructionLen == 4)
+ {
+ if (!NEXT_WORD(0))
+ return 0;
+ /* Get the major opcode of the ARCtangent-A5 32-bit instruction. */
+ state->_opcode = OPCODE(state->words[0]);
+ }
+ else
+ {
+ /* ARCompact 16-bit instruction */
+ if (!NEXT_WORD_AC(0))
+ return 0;
+ /* Get the major opcode of the ARCompact 16-bit instruction. */
+ state->_opcode = OPCODE_AC(state->words[0]);
+ }
+
+ instrName = 0;
+ decodingClass = 0; /* default! */
+ mul = 0;
+ condCodeIsPartOfName=0;
+ state->commNum = 0;
+ state->tcnt = 0;
+ state->acnt = 0;
+ state->flow = noflow;
+
+ if (state->commentBuffer)
+ state->commentBuffer[0] = '\0';
+
+ /* Find the match for the opcode. Once the major opcode category is
+ * identified, get the subopcode to determine the exact instruction.
+ * Based on the instruction identified, select the decoding class.
+ * If condition code is part of the instruction name, then set the
+ * flag 'condCodeIsPartOfName'.
+ * For branch, jump instructions set 'isBranch' (state->isBranch).
+ */
+
+ switch (state->_opcode)
+ {
+ case op_BC:
+ /* Branch Conditionally */
+ instrName = "b";
+ decodingClass = 13;
+ condCodeIsPartOfName = 1;
+ state->isBranch = 1;
+ break;
+
+ case op_BLC:
+ /* Branch and Link, Compare and Branch */
+ decodingClass = 9;
+ state->isBranch = 1;
+ switch (BITS(state->words[0],16,16))
+ {
+ case 0:
+ if (!instrName)
+ instrName = "bl";
+ decodingClass = 13;
+ condCodeIsPartOfName = 1;
+ break;
+ case 1:
+ switch (BITS(state->words[0],0,3))
+ {
+ case 0: instrName = "breq"; break;
+ case 1: instrName = "brne"; break;
+ case 2: instrName = "brlt"; break;
+ case 3: instrName = "brge"; break;
+ case 4: instrName = "brlo"; break;
+ case 5: instrName = "brhs"; break;
+ case 14: instrName = "bbit0"; break;
+ case 15: instrName = "bbit1"; break;
+ default:
+ instrName = "??? (0[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+ default:
+ instrName = "??? (0[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+
+ case op_LD:
+ /* Load register with offset [major opcode 2] */
+ decodingClass = 6;
+ switch (BITS(state->words[0],7,8))
+ {
+ case 0: instrName = "ld"; state->_load_len = 4; break;
+ case 1: instrName = "ldb"; state->_load_len = 1; break;
+ case 2: instrName = "ldw"; state->_load_len = 2; break;
+ default:
+ instrName = "??? (0[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+
+ case op_ST:
+ /* Store register with offset [major opcode 0x03] */
+ decodingClass = 7;
+ switch (BITS(state->words[0],1,2))
+ {
+ case 0: instrName = "st"; break;
+ case 1: instrName = "stb"; break;
+ case 2: instrName = "stw"; break;
+ default:
+ instrName = "??? (2[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+
+ case op_MAJOR_4:
+ /* ARC 32-bit basecase instructions with 3 Operands */
+ decodingClass = 0; /* Default for 3 operand instructions */
+ subopcode = BITS(state->words[0],16,21);
+ switch (subopcode)
+ {
+ case 0: instrName = "add"; break;
+ case 1: instrName = "adc"; break;
+ case 2: instrName = "sub"; break;
+ case 3: instrName = "sbc"; break;
+ case 4: instrName = "and"; break;
+ case 5: instrName = "or"; break;
+ case 6: instrName = "bic"; break;
+ case 7: instrName = "xor"; break;
+ case 8: instrName = "max"; break;
+ case 9: instrName = "min"; break;
+ case 10:
+ {
+ if(state->words[0] == 0x264a7000)
+ {
+ instrName = "nop";
+ decodingClass = 26;
+ }
+ else
+ {
+ instrName = "mov";
+ decodingClass = 12;
+ }
+ break;
+ }
+ case 11: instrName = "tst"; decodingClass = 2; break;
+ case 12: instrName = "cmp"; decodingClass = 2; break;
+ case 13: instrName = "rcmp"; decodingClass = 2; break;
+ case 14: instrName = "rsub"; break;
+ case 15: instrName = "bset"; break;
+ case 16: instrName = "bclr"; break;
+ case 17: instrName = "btst"; decodingClass = 2; break;
+ case 18: instrName = "bxor"; break;
+ case 19: instrName = "bmsk"; break;
+ case 20: instrName = "add1"; break;
+ case 21: instrName = "add2"; break;
+ case 22: instrName = "add3"; break;
+ case 23: instrName = "sub1"; break;
+ case 24: instrName = "sub2"; break;
+ case 25: instrName = "sub3"; break;
+ case 26: instrName = "mpylo"; break;
+ case 27: instrName = "mpyhi"; break;
+ case 28: instrName = "mpyhiu";break;
+ case 29: instrName = "mpylou";break;
+ case 32:
+ case 33:
+ instrName = "j";
+ case 34:
+ case 35:
+ if (!instrName) instrName = "jl";
+ decodingClass = 4;
+ condCodeIsPartOfName = 1;
+ state->isBranch = 1;
+ break;
+ case 40:
+ instrName = "lp";
+ decodingClass = 11;
+ condCodeIsPartOfName = 1;
+ state->isBranch = 1;
+ break;
+ case 41: instrName = "flag"; decodingClass = 3; break;
+ case 42: instrName = "lr"; decodingClass = 10; break;
+ case 43: instrName = "sr"; decodingClass = 8; break;
+ case 47:
+ decodingClass = 1;
+ switch (BITS(state->words[0],0,5)) /* Checking based on Subopcode2 */
+ {
+ case 0: instrName = "asl"; break;
+ case 1: instrName = "asr"; break;
+ case 2: instrName = "lsr"; break;
+ case 3: instrName = "ror"; break;
+ case 4: instrName = "rrc"; break;
+ case 5: instrName = "sexb"; break;
+ case 6: instrName = "sexw"; break;
+ case 7: instrName = "extb"; break;
+ case 8: instrName = "extw"; break;
+ case 9: instrName = "abs"; break;
+ case 10: instrName = "not"; break;
+ case 11: instrName = "rlc"; break;
+ case 12: instrName = "ex";
+
+
+ decodingClass = 34;
+ break; // ramana adds
+
+ case 63:
+ decodingClass = 26;
+ switch (BITS(state->words[0],24,26))
+ {
+ case 1 : instrName = "sleep"; decodingClass = 32; break;
+ case 2 :
+ if((info->mach) == ARC_MACH_ARC7)
+ instrName = "trap0";
+ else
+ instrName = "swi";
+ break;
+ case 3:
+
+ if(BITS(state->words[0],22,23) == 1)
+ instrName = "sync" ;
+
+ break;
+ case 4 : instrName = "rtie" ; break;
+ case 5 : instrName = "brk"; break;
+ default:
+
+ instrName = "???";
+ state->flow=invalid_instr;
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ if (!instrName)
+ {
+ subopcode = BITS(state->words[0],17,21);
+ decodingClass = 5;
+ switch (subopcode)
+ {
+ case 24: instrName = "ld"; state->_load_len = 4; break;
+ case 25: instrName = "ldb"; state->_load_len = 1; break;
+ case 26: instrName = "ldw"; state->_load_len = 2; break;
+ default:
+ instrName = "??? (0[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ }
+ break;
+
+ case op_MAJOR_5:
+ /* ARC 32-bit extension instructions */
+ decodingClass = 0; /* Default for Major opcode 5 ... */
+ subopcode = BITS(state->words[0],16,21);
+ switch (subopcode)
+ {
+ case 0: instrName = "asl"; break;
+ case 1: instrName = "lsr"; break;
+ case 2: instrName = "asr"; break;
+ case 3: instrName = "ror"; break;
+ case 4: instrName = "mul64"; mul =1; decodingClass = 2; break;
+ case 5: instrName = "mulu64"; mul =1; decodingClass = 2; break;
+
+ /* ARC A700 */
+ case 6: instrName = "adds" ;break;
+
+ case 7: instrName = "subs"; break;
+ case 8: instrName = "divaw"; break;
+ case 0xA: instrName = "asls"; break;
+ case 0xB: instrName = "asrs"; break;
+ case 0x28: instrName = "addsdw";break;
+ case 0x29: instrName = "subsdw"; break;
+
+ case 47:
+ switch(BITS(state->words[0],0,5))
+ {
+ case 0: instrName = "swap"; decodingClass = 1; break;
+ case 1: instrName = "norm"; decodingClass = 1; break;
+ /* ARC A700 DSP Extensions */
+ case 2: instrName = "sat16"; decodingClass = 1; break;
+ case 3: instrName = "rnd16"; decodingClass = 1; break;
+ case 4: instrName = "abssw"; decodingClass = 1; break;
+ case 5: instrName = "abss"; decodingClass = 1; break;
+ case 6: instrName = "negsw"; decodingClass = 1; break;
+ case 7: instrName = "negs"; decodingClass = 1; break;
+
+
+ case 8: instrName = "normw"; decodingClass = 1; break;
+ default:
+ instrName = "???";
+ state->flow =invalid_instr;
+ break;
+
+ }
+ break;
+ default:
+ instrName = "??? (2[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+
+
+ /* Aurora SIMD instruction support*/
+ case op_SIMD:
+
+ if (enable_simd)
+ {
+ decodingClass = 42;
+ subopcode = BITS(state->words[0], 17, 23);
+
+ switch (subopcode)
+ {
+
+ case 68:
+ instrName = "vld32";
+ decodingClass = 37;
+ usesSimdRegA=1;
+ usesSimdRegB=2;
+ usesSimdRegC=0;
+ simd_scale_u8 = 2;
+ break;
+
+ case 72:
+ instrName = "vld64";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 3;
+ break;
+
+ case 74:
+ instrName = "vld64w";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 3;
+ break;
+
+ case 70:
+ instrName = "vld32wl";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 2;
+ break;
+
+ case 66:
+ instrName = "vld32wh";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 2;
+ break;
+
+ case 76:
+ instrName = "vld128";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 4;
+ break;
+
+ case 78:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vld128r";
+ decodingClass = 38;
+ usesSimdRegA = 1;
+ usesSimdRegB = usesSimdRegC = 0;
+ break;
+ default:
+ instrName = "SIMD";
+ state->flow = invalid_instr;
+ }
+ }
+ break;
+ case 71:
+ instrName = "vst16_0";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 1;
+ break;
+
+ case 81:
+ instrName = "vst16_1";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 1;
+ break;
+
+ case 67:
+ instrName = "vst16_2";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 1;
+ break;
+
+ case 75:
+ instrName = "vst16_3";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 1;
+ break;
+
+ case 83:
+ instrName = "vst16_4";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 1;
+ break;
+
+ case 89:
+ instrName = "vst16_5";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 1;
+ break;
+
+ case 91:
+ instrName = "vst16_6";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 1;
+ break;
+
+ case 93:
+ instrName = "vst16_7";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 1;
+ break;
+
+ case 69:
+ instrName = "vst32_0";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 2;
+ break;
+
+ case 82:
+ instrName = "vst32_2";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 2;
+ break;
+
+ case 86:
+ instrName = "vst32_4";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 2;
+ break;
+
+ case 88:
+ instrName = "vst32_6";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 2;
+ break;
+
+ case 73:
+ instrName = "vst64";
+ decodingClass = 37 ;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 3;
+ break;
+
+ case 77:
+ instrName = "vst128";
+ decodingClass = 37;
+ usesSimdRegA = 1;
+ usesSimdRegB = 2;
+ usesSimdRegC = 0;
+ simd_scale_u8 = 4;
+ break;
+
+ case 79:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vst128r";
+ decodingClass = 38;
+ usesSimdRegA = 1;
+ usesSimdRegB = usesSimdRegC = 0;
+ break;
+
+ default:
+ instrName = "SIMD";
+ state->flow = invalid_instr;
+ }
+
+ }
+ break;
+ case 80:
+ instrName = "vmvw";
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ decodingClass = 39;
+ break;
+
+ case 84:
+ instrName = "vmvzw";
+ decodingClass = 39;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+
+ case 90:
+ instrName = "vmovw";
+ decodingClass = 39;
+ usesSimdRegA = 1;
+ usesSimdRegB = usesSimdRegC = 0;
+ break;
+
+ case 94:
+ instrName = "vmovzw";
+ decodingClass = 39;
+ usesSimdRegA = 1;
+ usesSimdRegB = usesSimdRegC = 0;
+ break;
+
+ case 85:
+ instrName = "vmvaw";
+ decodingClass = 39;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+
+ case 95:
+ instrName = "vmovaw";
+ decodingClass = 39;
+ usesSimdRegA = 1;
+ usesSimdRegB = usesSimdRegC = 0;
+ break;
+
+ case 10:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vaddw"; decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC =1;
+ break;
+
+ case 1:
+ instrName = "vaddaw"; decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC =1;
+ break;
+
+ case 2:
+ instrName = "vbaddw"; decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ }
+ break;
+ }
+
+ case 11:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vsubw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 1:
+ instrName = "vsubaw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 2:
+ instrName = "vbsubw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ }
+ }
+ break;
+
+ case 12:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vmulw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 1:
+ instrName = "vmulaw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 2:
+ instrName = "vbmulw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+
+ case 3:
+ instrName = "vbmulaw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ }
+ }
+ break;
+
+ case 13:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vmulfw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 1:
+ instrName = "vmulfaw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 2:
+ instrName = "vbmulfw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ }
+ }
+ break;
+
+ case 15:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vsummw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+ case 2:
+ instrName = "vbrsubw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ }
+ }
+ break;
+
+ case 23:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vmr7w";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 1:
+ instrName = "vmr7aw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+
+ case 2:
+ switch (BITS(state->words[0], 0, 5))
+ {
+ case 0:
+ instrName = "vaddsuw";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+
+ case 1:
+ instrName = "vabsw";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+
+ case 2:
+ instrName = "vsignw";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+
+ case 3:
+ instrName = "vupbw";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+
+ case 4:
+ instrName = "vexch1";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+
+ case 5:
+ instrName = "vexch2";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+
+ case 6:
+ instrName = "vexch4";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+
+ case 7:
+ instrName = "vupsbw";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+
+ case 8:
+ instrName = "vdirun";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = usesSimdRegA = 0;
+ break;
+
+ case 9:
+ instrName = "vdorun";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = usesSimdRegA = 0;
+ break;
+
+ case 10:
+ instrName = "vdiwr";
+ decodingClass = 40;
+ usesSimdRegB = 3;
+ usesSimdRegA = usesSimdRegC = 0;
+ fieldCisReg = 1;
+ break;
+
+ case 11:
+ instrName = "vdowr";
+ decodingClass = 40;
+ usesSimdRegB = 3;
+ usesSimdRegA = usesSimdRegC = 0;
+ fieldCisReg = 1;
+ break;
+
+ case 12:
+ instrName = "vdird";
+ decodingClass = 40;
+ usesSimdRegB = 1;
+ usesSimdRegC = 3;
+ usesSimdRegA = 0;
+ break;
+
+ case 13:
+ instrName = "vdord";
+ decodingClass = 40;
+ usesSimdRegB = 1;
+ usesSimdRegC = 3;
+ usesSimdRegA = 0;
+ break;
+
+ case 63:
+ {
+ switch (BITS(state->words[0], 24, 25))
+ {
+ case 0:
+ instrName = "vrec";
+ decodingClass = 43;
+ usesSimdRegC = 0;
+ usesSimdRegB = usesSimdRegA = 0;
+ break;
+
+ case 1:
+ instrName = "vrecrun";
+ decodingClass = 43;
+ usesSimdRegC = 0;
+ usesSimdRegA = usesSimdRegB = 0;
+ break;
+
+ case 2:
+ instrName = "vrun";
+ decodingClass = 43;
+ usesSimdRegC = 0;
+ usesSimdRegB = usesSimdRegA = 0;
+ break;
+
+ case 3:
+ instrName = "vendrec";
+ decodingClass = 43;
+ usesSimdRegC = 0;
+ usesSimdRegB = usesSimdRegA = 0;
+ break;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 3:
+ switch (BITS(state->words[0], 0, 2))
+ {
+ case 1:
+ instrName = "vabsaw";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+ case 3:
+ instrName = "vupbaw";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+ case 7:
+ instrName = "vupsbaw";
+ decodingClass = 40;
+ usesSimdRegC = usesSimdRegB = 1;
+ usesSimdRegA = 0;
+ break;
+ }
+ break;
+ }
+ }
+ break;
+
+ case 16:
+ instrName = "vasrw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 2;
+ break;
+
+ case 48:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vasrwi";
+ decodingClass = 41;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ case 2:
+ instrName = "vasrrwi";
+ decodingClass = 41;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ }
+ }
+ break;
+
+ case 59:
+ instrName = "vasrsrwi";
+ decodingClass = 41;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+
+ case 18:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vmaxw";
+ usesSimdRegC = 1;
+ break;
+ case 1:
+ instrName = "vmaxaw";
+ usesSimdRegC = 1;
+ break;
+ case 2:
+ instrName = "vbmaxw";
+ usesSimdRegC = 0;
+ break;
+ }
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ break;
+ }
+
+ case 19:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vminw";
+ usesSimdRegC = 1;
+ break;
+ case 1:
+ instrName = "vminaw";
+ usesSimdRegC = 0;
+ break;
+ case 2:
+ instrName = "vbminw";
+ usesSimdRegC = 0;
+ break;
+ }
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ break;
+ }
+
+ case 14:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vdifw";
+ break;
+ case 1:
+ instrName = "vdifaw";
+ break;
+ case 2:
+ instrName = "vmrb";
+ break;
+ }
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+ }
+
+ case 24:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vand";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+ case 1:
+ instrName = "vandaw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+ }
+ break;
+ }
+
+ case 25:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vor";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+ }
+ break;
+ }
+
+ case 26:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vxor";
+ break;
+ case 1:
+ instrName = "vxoraw";
+ break;
+ }
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+ }
+
+ case 27:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vbic";
+ break;
+ case 1:
+ instrName = "vbicaw";
+ break;
+ }
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+ }
+
+ case 4:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vavb";
+ break;
+ case 2:
+ instrName = "vavrb";
+ break;
+ }
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+ }
+
+ case 28:
+ instrName = "veqw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 29:
+ instrName = "vnew";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 30:
+ instrName = "vlew";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 31:
+ instrName = "vltw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ case 49:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vasrpwbi";
+ decodingClass = 41;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ case 2:
+ instrName = "vasrrpwbi";
+ decodingClass = 41;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ }
+ break;
+ }
+
+ case 5:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vsr8";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 2;
+ break;
+
+ case 1:
+ instrName = "vsr8aw";
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 2;
+ break;
+ }
+ break;
+ }
+
+ case 37:
+ {
+ short sub_subopcode = BITS(state->words[0], 15, 16);
+ switch (sub_subopcode)
+ {
+ case 0:
+ instrName = "vsr8i";
+ decodingClass = 41;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+
+ case 1:
+ instrName = "vsr8awi";
+ decodingClass = 41;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+ }
+ break;
+ }
+
+ case 20:
+ case 21:
+ case 22:
+ {
+ short subopcode2 = BITS(state->words[0], 15, 18);
+ switch (subopcode2)
+ {
+ case 0:
+ instrName = "vmr1w";
+ break;
+
+ case 2:
+ instrName = "vmr2w";
+ break;
+
+ case 4:
+ instrName = "vmr3w";
+ break;
+
+ case 6:
+ instrName = "vmr4w";
+ break;
+
+ case 8:
+ instrName = "vmr5w";
+ break;
+
+ case 10:
+ instrName = "vmr6w";
+ break;
+
+ case 1:
+ instrName = "vmr1aw";
+ break;
+
+ case 3:
+ instrName = "vmr2aw";
+ break;
+
+ case 5:
+ instrName = "vmr3aw";
+ break;
+
+ case 7:
+ instrName = "vmr4aw";
+ break;
+
+ case 9:
+ instrName = "vmr5aw";
+ break;
+
+ case 11:
+ instrName = "vmr6aw";
+ break;
+
+ }
+
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+ }
+
+
+ case 7:
+ case 6:
+ {
+ switch (BITS(state->words[0], 16, 19))
+ {
+ case 15:
+ instrName = "vh264ft";
+ break;
+ case 14:
+ instrName = "vh264f";
+ break;
+ case 13:
+ instrName = "vvc1ft";
+ break;
+ case 12:
+ instrName = "vvc1f";
+ break;
+ }
+ decodingClass = 42;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 1;
+ break;
+
+ }
+
+ case 92:
+ instrName = "vd6tapf";
+ decodingClass = 39;
+ usesSimdRegA = usesSimdRegB = 1;
+ usesSimdRegC = 0;
+ break;
+
+ case 55:
+ instrName = "vinti";
+ decodingClass = 43;
+ usesSimdRegA = usesSimdRegB = usesSimdRegC = 0;
+ break;
+
+ default:
+ instrName = "SIMD";
+ state->flow = invalid_instr;
+ break;
+ }
+ }
+ else
+ {
+ instrName = "???_SIMD";
+ state->flow = invalid_instr;
+ }
+ break;
+
+
+ case op_LD_ADD:
+ /* Load/Add resister-register */
+ decodingClass = 15; /* default for Major opcode 12 ... */
+ switch(BITS(state->words[0],3,4))
+ {
+ case 0: instrName = "ld_s"; break;
+ case 1: instrName = "ldb_s"; break;
+ case 2: instrName = "ldw_s"; break;
+ case 3: instrName = "add_s"; break;
+ default:
+ instrName = "??? (2[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+
+ case op_ADD_SUB_SHIFT:
+ /* Add/sub/shift immediate */
+ decodingClass = 16; /* default for Major opcode 13 ... */
+ switch(BITS(state->words[0],3,4))
+ {
+ case 0: instrName = "add_s"; break;
+ case 1: instrName = "sub_s"; break;
+ case 2: instrName = "asl_s"; break;
+ case 3: instrName = "asr_s"; break;
+ default:
+ instrName = "??? (2[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+
+ case op_ADD_MOV_CMP:
+ /* One Dest/Source can be any of r0 - r63 */
+ decodingClass = 17; /* default for Major opcode 14 ... */
+ switch(BITS(state->words[0],3,4))
+ {
+ case 0: instrName = "add_s"; break;
+ case 1:
+ case 3: instrName = "mov_s"; decodingClass = 18; break;
+ case 2: instrName = "cmp_s"; decodingClass = 18; break;
+ default:
+ instrName = "??? (2[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+
+ case op_S:
+ /* ARCompact 16-bit instructions, General ops/ single ops */
+ decodingClass = 22; /* default for Major opcode 15 ... */
+ switch(BITS(state->words[0],0,4))
+ {
+ case 0:
+ decodingClass = 27;
+ switch(BITS(state->words[0],5,7))
+ {
+ case 0 : instrName = "j_s";
+ case 2 : if (!instrName) instrName = "jl_s";
+ state->isBranch = 1;
+ state->nullifyMode = BR_exec_when_no_jump;
+ break;
+ case 1 : if (!instrName) instrName = "j_s.d";
+ case 3 : if (!instrName) instrName = "jl_s.d";
+ state->isBranch = 1;
+ state->nullifyMode = BR_exec_always;
+ break;
+ case 6 : instrName = "sub_s.ne";
+ decodingClass = 35;
+ break;
+ case 7 :
+ decodingClass = 26;
+ switch(BITS(state->words[0],8,10))
+ {
+ case 0 : instrName = "nop_s"; break;
+
+ /* Unimplemented instruction reserved in ARC700 */
+ case 1: instrName = "unimp_s";break;
+
+
+ case 4: instrName = "jeq_s [blink]";
+ case 5: if (!instrName) instrName = "jne_s [blink]";
+ case 6:
+ if (!instrName)
+ instrName = "j_s [blink]";
+ state->isBranch = 1;
+ state->nullifyMode = BR_exec_when_no_jump;
+ break;
+ case 7:
+ if (!instrName)
+ {
+ instrName = "j_s.d [blink]";
+ state->flow = indirect_jump;
+ state->register_for_indirect_jump = 31; /* blink is r31 */
+ }
+ state->isBranch = 1;
+ state->nullifyMode = BR_exec_always;
+ break;
+ default:
+ instrName = "??? (2[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+ default:
+ instrName = "??? (2[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+ case 2 : instrName = "sub_s"; break;
+ case 4 : instrName = "and_s"; break;
+ case 5 : instrName = "or_s"; break;
+ case 6 : instrName = "bic_s"; break;
+ case 7 : instrName = "xor_s"; break;
+ case 11: instrName = "tst_s"; decodingClass = 14; break;
+ case 12: instrName = "mul64_s"; mul =1; decodingClass = 14; break;
+ case 13: instrName = "sexb_s"; decodingClass = 14; break;
+ case 14: instrName = "sexw_s"; decodingClass = 14; break;
+ case 15: instrName = "extb_s"; decodingClass = 14; break;
+ case 16: instrName = "extw_s"; decodingClass = 14; break;
+ case 17: instrName = "abs_s"; decodingClass = 14; break;
+ case 18: instrName = "not_s"; decodingClass = 14; break;
+ case 19: instrName = "neg_s"; decodingClass = 14; break;
+ case 20: instrName = "add1_s"; break;
+ case 21: instrName = "add2_s"; break;
+ case 22: instrName = "add3_s"; break;
+ case 24: instrName = "asl_s"; break;
+ case 25: instrName = "lsr_s"; break;
+ case 26: instrName = "asr_s"; break;
+ case 27: instrName = "asl_s"; decodingClass = 14; break;
+ case 28: instrName = "asr_s"; decodingClass = 14; break;
+ case 29: instrName = "lsr_s"; decodingClass = 14; break;
+ case 30: instrName = "trap_s"; decodingClass = 33; break;
+ case 31: instrName = "brk_s"; decodingClass = 26; break;
+
+ default:
+ instrName = "??? (2[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+
+ case op_LD_S:
+ /* ARCompact 16-bit Load with offset, Major Opcode 0x10 */
+ instrName = "ld_s";
+ decodingClass = 28;
+ break;
+
+ case op_LDB_S:
+ /* ARCompact 16-bit Load with offset, Major Opcode 0x11 */
+ instrName = "ldb_s";
+ decodingClass = 28;
+ break;
+
+ case op_LDW_S:
+ /* ARCompact 16-bit Load with offset, Major Opcode 0x12 */
+ instrName = "ldw_s";
+ decodingClass = 28;
+ break;
+
+ case op_LDWX_S:
+ /* ARCompact 16-bit Load with offset, Major Opcode 0x13 */
+ instrName = "ldw_s.x";
+ decodingClass = 28;
+ break;
+
+ case op_ST_S:
+ /* ARCompact 16-bit Store with offset, Major Opcode 0x14 */
+ instrName = "st_s";
+ decodingClass = 28;
+ break;
+
+ case op_STB_S:
+ /* ARCompact 16-bit Store with offset, Major Opcode 0x15 */
+ instrName = "stb_s";
+ decodingClass = 28;
+ break;
+
+ case op_STW_S:
+ /* ARCompact 16-bit Store with offset, Major Opcode 0x16 */
+ instrName = "stw_s";
+ decodingClass = 28;
+ break;
+
+ case op_Su5:
+ /* ARCompact 16-bit involving unsigned 5-bit immediate operand */
+ decodingClass = 23; /* default for major opcode 0x17 ... */
+ switch (BITS(state->words[0],5,7))
+ {
+ case 0: instrName = "asl_s"; break;
+ case 1: instrName = "lsr_s"; break;
+ case 2: instrName = "asr_s"; break;
+ case 3: instrName = "sub_s"; break;
+ case 4: instrName = "bset_s"; break;
+ case 5: instrName = "bclr_s"; break;
+ case 6: instrName = "bmsk_s"; break;
+ case 7: instrName = "btst_s"; decodingClass = 21; break;
+ }
+ break;
+
+ case op_SP:
+ /* ARCompact 16-bit Stack pointer-based instructions */
+ decodingClass = 19; /* default for Stack pointer-based insns ... */
+ switch (BITS(state->words[0],5,7))
+ {
+ case 0: instrName = "ld_s"; break;
+ case 1: instrName = "ldb_s"; break;
+ case 2: instrName = "st_s"; break;
+ case 3: instrName = "stb_s"; break;
+ case 4: instrName = "add_s"; break;
+ case 5:
+ if (!BITS(state->words[0],8,8))
+ instrName = "add_s";
+ else
+ instrName = "sub_s";
+ break;
+ case 6: instrName = "pop_s"; decodingClass = 31; break;
+ case 7: instrName = "push_s"; decodingClass = 31; break;
+ default:
+ instrName = "??? (2[3])";
+ state->flow = invalid_instr;
+ break;
+ }
+ break;
+
+ case op_GP:
+ /* ARCompact 16-bit Gp-based ld/add (data aligned offset) */
+ decodingClass = 20; /* default for gp-relative insns ... */
+ switch (BITS(state->words[0],9,10))
+ {
+ case 0: instrName = "ld_s"; break;
+ case 1: instrName = "ldb_s"; break;
+ case 2: instrName = "ldw_s"; break;
+ case 3: instrName = "add_s"; break;
+ }
+ break;
+
+ case op_Pcl:
+ /* ARCompact 16-bit Pcl-based ld (32-bit aligned offset) */
+ instrName = "ld_s";
+ decodingClass = 29;
+ break;
+
+ case op_MOV_S:
+ /* ARCompact 16-bit Move immediate */
+ instrName = "mov_s";
+ decodingClass = 30;
+ break;
+
+ case op_ADD_CMP:
+ /* ARCompact 16-bit Add/compare immediate */
+ decodingClass = 21; /* default for major opcode 0x1c ... */
+ if (BIT(state->words[0],7))
+ instrName = "cmp_s";
+ else
+ instrName = "add_s";
+ break;
+
+ case op_BR_S:
+ /* ARCompact 16-bit Branch conditionally on reg z/nz */
+ decodingClass = 25; /* Default for BR_S instruction ... */
+ if (BIT(state->words[0],7))
+ instrName = "brne_s";
+ else
+ instrName = "breq_s";
+ state->isBranch = 1;
+ break;
+
+ case op_B_S:
+ /* ARCompact 16-bit Branch conditionally */
+ decodingClass = 24; /* Default for B_S instruction ... */
+ state->isBranch = 1;
+ switch (BITS(state->words[0],9,10))
+ {
+ case 0: instrName = "b_s"; break;
+ case 1: instrName = "beq_s"; break;
+ case 2: instrName = "bne_s"; break;
+ case 3:
+ switch (BITS(state->words[0],6,8))
+ {
+ case 0: instrName = "bgt_s"; break;
+ case 1: instrName = "bge_s"; break;
+ case 2: instrName = "blt_s"; break;
+ case 3: instrName = "ble_s"; break;
+ case 4: instrName = "bhi_s"; break;
+ case 5: instrName = "bhs_s"; break;
+ case 6: instrName = "blo_s"; break;
+ case 7: instrName = "bls_s"; break;
+ }
+ break;
+ }
+ break;
+
+ case op_BL_S:
+ /* ARCompact 16-bit Branch and link unconditionally */
+ decodingClass = 24; /* Default for B_S instruction ... */
+ instrName = "bl_s";
+ state->isBranch = 1;
+ break;
+
+ default:
+ instrName = instruction_name (state, state->_opcode, 0, &flags);
+ if (!instrName)
+ {
+ instrName = "???";
+ state->flow=invalid_instr;
+ }
+ break;
+ }
+
+ /* Maybe we should be checking for extension instructions over here
+ * instead of all over this crazy switch case. */
+ if (state->flow == invalid_instr)
+ {
+ if (!((state->_opcode == op_SIMD) && enable_simd))
+ instrName = instruction_name(state,state->_opcode,
+ state->words[0],
+ &flags);
+
+ if (state->instructionLen == 2)
+ {
+ switch (flags)
+ {
+ case AC_SYNTAX_3OP:
+ decodingClass = 22;
+ break;
+ case AC_SYNTAX_2OP:
+ decodingClass = 14;
+ break;
+ case AC_SYNTAX_1OP:
+ decodingClass = 36;
+ break;
+ case AC_SYNTAX_NOP:
+ decodingClass = 26;
+ break;
+ default:
+ mwerror(state, "Invalid syntax class\n");
+ }
+ }
+ else
+ {
+/* Must do the above for this one too */
+ switch (flags)
+ {
+ case AC_SYNTAX_3OP:
+ decodingClass = 0;
+ break;
+ case AC_SYNTAX_2OP:
+ decodingClass = 1;
+ break;
+ case AC_SYNTAX_1OP:
+ decodingClass = 32;
+ break;
+ case AC_SYNTAX_NOP:
+ break;
+ case AC_SYNTAX_SIMD:
+ break;
+ default:
+ mwerror(state, "Invalid syntax class\n");
+ }
+ }
+
+ if (!instrName)
+ {
+ instrName = "???";
+ state->flow=invalid_instr;
+ }
+ }
+
+ fieldAisReg = fieldBisReg = fieldCisReg = 1; /* assume regs for now */
+ flag = cond = is_shimm = is_limm = 0;
+ signExtend = addrWriteBack = directMem = 0;
+ usesAuxReg = 0;
+
+ /* The following module decodes the instruction */
+ switch (decodingClass)
+ {
+ case 0:
+
+ /* For ARCtangent 32-bit instructions with 3 operands */
+
+ subopcode = BITS(state->words[0],22,23);
+ switch (subopcode)
+ {
+ case 0:
+
+ /* Either fieldB or fieldC or both can be a limm value;
+ * fieldA can be 0;
+ */
+
+ CHECK_FIELD_C();
+ if (!is_limm)
+ {
+ /* If fieldC is not a limm, then fieldB may be a limm value */
+ CHECK_FIELD_B();
+ }
+ else
+ {
+ FIELD_B();
+ if (!fieldBisReg)
+ fieldB = fieldC;
+ }
+ CHECK_FIELD_A();
+ CHECK_FLAG();
+ break;
+
+ case 1:
+
+ /* fieldB may ba a limm value
+ * fieldC is a shimm (unsigned 6-bit immediate)
+ * fieldA can be 0
+ */
+
+ CHECK_FIELD_B();
+ FIELD_C();
+ fieldCisReg = 0;
+ /* Say ea is not present, so only one of us will do the
+ name lookup. */
+ state->_offset += fieldB, state->_ea_present = 0;
+ CHECK_FIELD_A();
+ CHECK_FLAG();
+ break;
+
+ case 2:
+
+ /* fieldB may ba a limm value
+ * fieldC is a shimm (signed 12-bit immediate)
+ * fieldA can be 0
+ */
+
+ fieldCisReg = 0;
+ fieldC = FIELDS(state->words[0]);
+ CHECK_FIELD_B();
+ /* Say ea is not present, so only one of us will do the
+ name lookup. */
+ state->_offset += fieldB, state->_ea_present = 0;
+ if (is_limm)
+ fieldAisReg = fieldA = 0;
+ else
+ fieldA = fieldB;
+ CHECK_FLAG();
+ break;
+
+ case 3:
+
+ /* fieldB may ba a limm value
+ * fieldC may be a limm or a shimm (unsigned 6-bit immediate)
+ * fieldA can be 0
+ * Conditional instructions
+ */
+
+ CHECK_FIELD_B();
+ /* fieldC is a shimm (unsigned 6-bit immediate) */
+ if (is_limm)
+ {
+ fieldAisReg = fieldA = 0;
+ FIELD_C();
+ if (BIT(state->words[0],5))
+ fieldCisReg = 0;
+ else if (fieldC == 62)
+ {
+ fieldCisReg = 0;
+ fieldC = fieldB;
+ }
+ }
+ else
+ {
+ fieldA = fieldB;
+ if (BIT(state->words[0],5))
+ {
+ FIELD_C();
+ fieldCisReg = 0;
+ }
+ else
+ {
+ CHECK_FIELD_C();
+ }
+ }
+ CHECK_FLAG_COND();
+ break;
+ }
+
+ write_instr_name();
+ WRITE_FORMAT_x(A);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldA, fieldB, fieldC);
+ write_comments();
+ break;
+
+ case 1:
+
+ /* For ARCtangent 32-bit instructions with 2 operands */
+
+ /* field C is either a register or limm (different!) */
+ CHECK_FIELD_C();
+ FIELD_B();
+ CHECK_FLAG();
+
+ if (BITS(state->words[0],22,23) == 1 )
+ fieldCisReg = 0;
+ if (fieldCisReg) state->ea_reg1 = fieldC;
+ /* field C is either a shimm (same as fieldC) or limm (different!) */
+ /* Say ea is not present, so only one of us will do the name lookup. */
+ else state->_offset += fieldB, state->_ea_present = 0;
+
+ write_instr_name();
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ write_comments();
+ break;
+
+ case 2:
+
+ /* For BTST, CMP, MUL64, MULU64 instruction */
+
+ /* field C is either a register or limm (different!) */
+ subopcode = BITS(state->words[0],22,23);
+ if (subopcode == 0 || ((subopcode == 3) && (!BIT(state->words[0],5))))
+ {
+ CHECK_FIELD_C();
+ if (is_limm)
+ {
+ FIELD_B();
+ if (!fieldBisReg)
+ fieldB = fieldC;
+ }
+ else
+ {
+ CHECK_FIELD_B();
+ }
+ }
+ else if (subopcode == 1 || ((subopcode == 3) && (BIT(state->words[0],5))))
+ {
+ FIELD_C();
+ fieldCisReg = 0;
+ CHECK_FIELD_B();
+ }
+ else if (subopcode == 2)
+ {
+ FIELD_B();
+ fieldC = FIELDS(state->words[0]);
+ fieldCisReg = 0;
+ }
+ if (subopcode == 3)
+ CHECK_COND();
+
+ if (fieldCisReg) state->ea_reg1 = fieldC;
+ /* field C is either a shimm (same as fieldC) or limm (different!) */
+ /* Say ea is not present, so only one of us will do the name lookup. */
+ else state->_offset += fieldB, state->_ea_present = 0;
+
+ write_instr_name();
+ if (mul)
+ {
+ /* For Multiply instructions, the first operand is 0 */
+ WRITE_FORMAT_x(A);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, 0, fieldB, fieldC);
+ }
+ else
+ {
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ }
+ write_comments();
+ break;
+
+ case 3:
+ /*
+ * For FLAG instruction
+ */
+ subopcode = BITS(state->words[0],22,23);
+
+ if (subopcode == 0 || ((subopcode == 3) && (!BIT(state->words[0],5))))
+ {
+ CHECK_FIELD_C();
+ }
+ else if (subopcode == 1 || ((subopcode == 3) && (BIT(state->words[0],5))))
+ {
+ FIELD_C();
+ fieldCisReg = 0;
+ }
+ else if (subopcode == 2)
+ {
+ fieldC = FIELDS(state->words[0]);
+ fieldCisReg = 0;
+ }
+ if (subopcode == 3)
+ CHECK_COND();
+ flag = 0; /* this is the FLAG instruction -- it's redundant */
+
+ write_instr_name();
+ WRITE_FORMAT_x(C);
+ my_sprintf(state, state->operandBuffer, formatString, fieldC);
+ write_comments();
+ break;
+
+ case 4:
+ /*
+ * For op_JC -- jump to address specified.
+ * Also covers jump and link--bit 9 of the instr. word
+ * selects whether linked, thus "is_linked" is set above.
+ */
+ subopcode = BITS(state->words[0],22,23);
+ if (subopcode == 0 || ((subopcode == 3) && (!BIT(state->words[0],5))))
+ {
+ CHECK_FIELD_C();
+ /* ilink registers */
+ if (fieldC == 29 || fieldC == 31)
+ CHECK_FLAG();
+ }
+ else if (subopcode == 1 || ((subopcode == 3) && (BIT(state->words[0],5))))
+ {
+ FIELD_C();
+ fieldCisReg = 0;
+ }
+ else if (subopcode == 2)
+ {
+ fieldC = FIELDS(state->words[0]);
+ fieldCisReg = 0;
+ }
+
+ if (subopcode == 3)
+ CHECK_COND();
+
+ state->nullifyMode = BITS(state->words[0],16,16);
+
+ if (!fieldCisReg)
+ {
+ state->flow = is_linked ? direct_call : direct_jump;
+ add_target(fieldC);
+ }
+ else
+ {
+ state->flow = is_linked ? indirect_call : indirect_jump;
+ /*
+ * We should also treat this as indirect call if NOT linked
+ * but the preceding instruction was a "lr blink,[status]"
+ * and we have a delay slot with "add blink,blink,2".
+ * For now we can't detect such.
+ */
+ state->register_for_indirect_jump = fieldC;
+ }
+
+ write_instr_name();
+ strcat(formatString,
+ IS_REG(C)?"[%r]":"%s"); /* address/label name */
+
+ if (IS_REG(C))
+ my_sprintf(state, state->operandBuffer, formatString, fieldC);
+ else
+ my_sprintf(state, state->operandBuffer, formatString,
+ post_address(state, fieldC));
+ write_comments();
+ break;
+
+ case 5:
+ /* LD instruction. B and C can be regs, or one or both can be limm. */
+
+ CHECK_FIELD_A();
+ CHECK_FIELD_B();
+
+ if(FIELDA(state->words[0]) == 62)
+ {
+ instrName = "prefetch";
+ }
+
+
+
+ if (is_limm)
+ {
+ FIELD_C();
+ if (!fieldCisReg)
+ fieldC = fieldB;
+ }
+ else
+ {
+ CHECK_FIELD_C();
+ }
+ if (dbg) printf("5:b reg %d %d c reg %d %d \n",
+ fieldBisReg,fieldB,fieldCisReg,fieldC);
+ state->_offset = 0;
+ state->_ea_present = 1;
+ if (fieldBisReg) state->ea_reg1 = fieldB; else state->_offset += fieldB;
+ if (fieldCisReg) state->ea_reg2 = fieldC; else state->_offset += fieldC;
+ state->_mem_load = 1;
+
+ directMem = BIT(state->words[0],15);
+ /* Check if address writeback is allowed before decoding the
+ address writeback field of a load instruction.*/
+ if (fieldBisReg && (fieldB != 62))
+ addrWriteBack = BITS(state->words[0],22,23);
+ signExtend = BIT(state->words[0],16);
+
+ write_instr_name();
+
+ /* Check for prefetch or ld 0,...*/
+ if(IS_REG(A))
+ WRITE_FORMAT_x_COMMA_LB(A);
+ else
+ {
+ strcat(formatString,"%*");
+ WRITE_FORMAT_LB();
+ }
+
+
+ if (fieldBisReg || fieldB != 0)
+ WRITE_FORMAT_x(B);
+ else
+ fieldB = fieldC;
+
+ WRITE_FORMAT_COMMA_x_RB(C);
+ my_sprintf(state, state->operandBuffer, formatString, fieldA, fieldB, fieldC);
+ write_comments();
+ break;
+
+ case 6:
+ /* LD instruction. */
+ CHECK_FIELD_B();
+ CHECK_FIELD_A();
+ /* Support for Prefetch */
+ /* Fixme :: Check for A700 within this function */
+
+ if(FIELDA(state->words[0]) == 62)
+ {
+ instrName = "prefetch";
+ }
+
+ fieldC = FIELDD9(state->words[0]);
+ fieldCisReg = 0;
+
+ if (dbg) printf_unfiltered("6:b reg %d %d c 0x%x \n",
+ fieldBisReg,fieldB,fieldC);
+ state->_ea_present = 1;
+ state->_offset = fieldC;
+ state->_mem_load = 1;
+ if (fieldBisReg) state->ea_reg1 = fieldB;
+ /* field B is either a shimm (same as fieldC) or limm (different!) */
+ /* Say ea is not present, so only one of us will do the name lookup. */
+ else state->_offset += fieldB, state->_ea_present = 0;
+
+ directMem = BIT(state->words[0],11);
+ /* Check if address writeback is allowed before decoding the
+ address writeback field of a load instruction.*/
+ if (fieldBisReg && (fieldB != 62))
+ addrWriteBack = BITS(state->words[0],9,10);
+ signExtend = BIT(state->words[0],6);
+
+ write_instr_name();
+ if(IS_REG(A))
+ WRITE_FORMAT_x_COMMA_LB(A);
+ else
+ {
+ strcat(formatString,"%*");
+ WRITE_FORMAT_LB();
+ }
+ if (!fieldBisReg)
+ {
+ fieldB = state->_offset;
+ WRITE_FORMAT_x_RB(B);
+ }
+ else
+ {
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x_RB(C);
+ }
+ my_sprintf(state, state->operandBuffer, formatString, fieldA, fieldB, fieldC);
+ write_comments();
+ break;
+
+ case 7:
+ /* ST instruction. */
+ CHECK_FIELD_B ();
+ CHECK_FIELD_C ();
+ state->source_operand.registerNum = fieldC;
+ state->sourceType = fieldCisReg ? ARC_REGISTER : ARC_LIMM;
+ fieldA = FIELDD9 (state->words[0]); /* shimm */
+ fieldAisReg = 0;
+
+ /* [B,A offset] */
+ if (dbg) printf_unfiltered("7:b reg %d %x off %x\n",
+ fieldBisReg,fieldB,fieldA);
+ state->_ea_present = 1;
+ state->_offset = fieldA;
+ if (fieldBisReg) state->ea_reg1 = fieldB;
+ /*
+ * field B is either a shimm (same as fieldA) or limm (different!)
+ * Say ea is not present, so only one of us will do the name lookup.
+ * (for is_limm we do the name translation here).
+ */
+ else
+ state->_offset += fieldB, state->_ea_present = 0;
+
+ directMem = BIT (state->words[0], 5);
+ addrWriteBack = BITS (state->words[0], 3, 4);
+ state->_addrWriteBack = addrWriteBack;
+ write_instr_name ();
+ WRITE_FORMAT_x_COMMA_LB (C);
+ if (fieldA == 0)
+ {
+ WRITE_FORMAT_x_RB(B);
+ }
+ else
+ {
+ WRITE_FORMAT_x(B);
+ fieldAisReg = 0;
+ WRITE_FORMAT_COMMA_x_RB(A);
+ }
+ my_sprintf(state, state->operandBuffer, formatString, fieldC, fieldB, fieldA);
+ write_comments2(fieldA);
+ break;
+
+ case 8:
+ /* SR instruction */
+ CHECK_FIELD_B();
+ switch (BITS(state->words[0],22,23))
+ {
+ case 0:
+ if (is_limm)
+ {
+ FIELD_C();
+ if (!fieldCisReg)
+ fieldC = fieldB;
+ }
+ else
+ {
+ CHECK_FIELD_C();
+ }
+ break;
+ case 1:
+ FIELD_C();
+ fieldCisReg = 0;
+ break;
+ case 2:
+ fieldC = FIELDS(state->words[0]);
+ fieldCisReg = 0;
+ break;
+ }
+
+ write_instr_name();
+ WRITE_FORMAT_x_COMMA_LB(B);
+ /* Try to print B as an aux reg if it is not a core reg. */
+ usesAuxReg = 1;
+ WRITE_FORMAT_x(C);
+ WRITE_FORMAT_RB();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ write_comments();
+ break;
+
+ case 9:
+ /* BBIT0/BBIT1 Instruction */
+
+ CHECK_FIELD_C();
+ if (is_limm || BIT(state->words[0],4))
+ {
+ fieldCisReg = 0;
+ FIELD_B();
+ }
+ else
+ {
+ CHECK_FIELD_B();
+ }
+ fieldAisReg = fieldA = 0;
+ fieldA = FIELDS9(state->words[0]);
+ fieldA += (addr & ~0x3);
+ CHECK_NULLIFY();
+
+ write_instr_name();
+
+ add_target(fieldA);
+ state->flow = state->_opcode == op_BLC ? direct_call : direct_jump;
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ strcat(formatString, ",%s"); /* address/label name */
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC, post_address(state, fieldA));
+ write_comments();
+ break;
+
+ case 10:
+ /* LR instruction */
+ CHECK_FIELD_B();
+ switch (BITS(state->words[0],22,23))
+ {
+ case 0:
+ CHECK_FIELD_C(); break;
+ case 1:
+ FIELD_C();
+ fieldCisReg = 0;
+ break;
+ case 2:
+ fieldC = FIELDS(state->words[0]);
+ fieldCisReg = 0;
+ break;
+ }
+
+ write_instr_name();
+ WRITE_FORMAT_x_COMMA_LB(B);
+ /* Try to print B as an aux reg if it is not a core reg. */
+ usesAuxReg = 1;
+ WRITE_FORMAT_x(C);
+ WRITE_FORMAT_RB();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ write_comments();
+ break;
+
+ case 11:
+ /* lp instruction */
+
+ if (BITS(state->words[0],22,23) == 3)
+ {
+ FIELD_C();
+ CHECK_COND();
+ }
+ else
+ {
+ fieldC = FIELDS(state->words[0]);
+ }
+
+ fieldC = fieldC << 1;
+ fieldC += (addr & ~0x3);
+
+ write_instr_name();
+
+ /* This address could be a label we know. Convert it. */
+ add_target(fieldC);
+ state->flow = state->_opcode == op_BLC ? direct_call : direct_jump;
+
+ fieldCisReg = 0;
+ strcat(formatString, "%s"); /* address/label name */
+ my_sprintf(state, state->operandBuffer, formatString, post_address(state, fieldC));
+ write_comments();
+ break;
+
+ case 12:
+ /* MOV instruction */
+ FIELD_B();
+ subopcode = BITS(state->words[0],22,23);
+ if (subopcode == 0 || ((subopcode == 3) && (!BIT(state->words[0],5))))
+ {
+ CHECK_FIELD_C();
+ }
+ else if (subopcode == 1 || ((subopcode == 3) && (BIT(state->words[0],5))))
+ {
+ FIELD_C();
+ fieldCisReg = 0;
+ }
+ else if (subopcode == 2)
+ {
+ fieldC = FIELDS(state->words[0]);
+ fieldCisReg = 0;
+ }
+ if (subopcode == 3)
+ {
+ CHECK_FLAG_COND();
+ }
+ else
+ {
+ CHECK_FLAG();
+ }
+
+ write_instr_name();
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ break;
+
+ case 13:
+ /* "B", "BL" instruction */
+
+ fieldA = 0;
+ if ((state->_opcode == op_BC && (BIT(state->words[0],16))) ||
+ (state->_opcode == op_BLC && (BIT(state->words[0],17))))
+ {
+ /* unconditional branch s25 or branch and link d25 */
+ fieldA = (BITS(state->words[0],0,4)) << 10;
+ }
+ fieldA |= BITS(state->words[0],6,15);
+
+ if (state->_opcode == op_BLC)
+ {
+ /* Fix for Bug #553. A bl unconditional has only 9 bits in the
+ * least order bits. */
+ fieldA = fieldA << 9;
+ fieldA |= BITS(state->words[0],18,26);
+ fieldA = fieldA << 2;
+ }
+ else
+ {
+ fieldA = fieldA << 10;
+ fieldA |= BITS(state->words[0],17,26);
+ fieldA = fieldA << 1;
+ }
+
+ if ((state->_opcode == op_BC && (BIT(state->words[0],16))) ||
+ (state->_opcode == op_BLC && (BIT(state->words[0],17))))
+ /* unconditional branch s25 or branch and link d25 */
+ fieldA = sign_extend(fieldA, 25);
+ else
+ /* conditional branch s21 or branch and link d21 */
+ fieldA = sign_extend(fieldA, 21);
+
+ fieldA += (addr & ~0x3);
+
+ if (BIT(state->words[0],16) && state->_opcode == op_BC)
+ CHECK_NULLIFY();
+ else
+ /* Checking for bl unconditionally FIX For Bug #553 */
+ if((state->_opcode == op_BLC && BITS(state->words[0],16,17) == 2 )
+ ||(state->_opcode == op_BC && (BIT(state->words[0],16))))
+ CHECK_NULLIFY();
+ else
+ CHECK_COND_NULLIFY();
+
+
+
+ write_instr_name();
+ /* This address could be a label we know. Convert it. */
+ add_target(fieldA); /* For debugger. */
+ state->flow = state->_opcode == op_BLC /* BL */
+ ? direct_call
+ : direct_jump;
+ /* indirect calls are achieved by "lr blink,[status]; */
+ /* lr dest<- func addr; j [dest]" */
+
+ strcat(formatString, "%s"); /* address/label name */
+ my_sprintf(state, state->operandBuffer, formatString, post_address(state, fieldA));
+ write_comments();
+ break;
+
+ case 14:
+
+ /* Extension Instructions */
+
+ FIELD_C_AC();
+ FIELD_B_AC();
+
+ write_instr_name();
+ if (mul)
+ {
+ fieldA = fieldAisReg = 0;
+ WRITE_FORMAT_x(A);
+ WRITE_FORMAT_COMMA_x(B);
+ }
+ else
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ if (mul)
+ my_sprintf(state, state->operandBuffer, formatString, 0, fieldB, fieldC);
+ else
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ break;
+
+ case 15:
+
+ /* ARCompact 16-bit Load/Add resister-register */
+
+ FIELD_C_AC();
+ FIELD_B_AC();
+ FIELD_A_AC();
+
+ write_instr_name();
+
+ if (BITS(state->words[0],3,4) != 3)
+ {
+ WRITE_FORMAT_x_COMMA_LB(A);
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x_RB(C);
+ }
+ else
+ {
+ WRITE_FORMAT_x(A);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ }
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldA, fieldB, fieldC);
+ break;
+
+ case 16:
+
+ /* ARCompact 16-bit Add/Sub/Shift instructions */
+
+ FIELD_C_AC();
+ FIELD_B_AC();
+ fieldA = FIELDA_AC(state->words[0]);
+ fieldAisReg = 0;
+
+ write_instr_name();
+ WRITE_FORMAT_x(C);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(A);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldC, fieldB, fieldA);
+ break;
+
+ case 17:
+
+ /* add_s instruction, one Dest/Source can be any of r0 - r63 */
+
+ CHECK_FIELD_H_AC();
+ FIELD_B_AC();
+
+ write_instr_name();
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldB, fieldC);
+ break;
+
+ case 18:
+
+ /* mov_s/cmp_s instruction, one Dest/Source can be any of r0 - r63 */
+
+ if ((BITS(state->words[0],3,4) == 1) || (BITS(state->words[0],3,4) == 2))
+ {
+ CHECK_FIELD_H_AC();
+ }
+ else if (BITS(state->words[0],3,4) == 3)
+ {
+ FIELD_H_AC();
+ }
+ FIELD_B_AC();
+
+ write_instr_name();
+ if (BITS(state->words[0],3,4) == 3)
+ {
+ WRITE_FORMAT_x(C);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldC, fieldB);
+ }
+ else
+ {
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ }
+ break;
+
+ case 19:
+
+ /* Stack pointer-based instructions [major opcode 0x18] */
+
+ if (BITS(state->words[0],5,7) == 5)
+ fieldA = 28;
+ else
+ {
+ FIELD_B_AC();
+ fieldA = fieldB;
+ }
+ fieldB = 28; /* Field B is the stack pointer register */
+ fieldC = (FIELDU_AC(state->words[0])) << 2;
+ fieldCisReg = 0;
+
+ write_instr_name();
+
+ switch (BITS(state->words[0],5,7))
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ WRITE_FORMAT_x_COMMA_LB(A);
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x_RB(C);
+ break;
+ case 4:
+ case 5:
+ WRITE_FORMAT_x(A);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ break;
+ }
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldA, fieldB, fieldC);
+ break;
+
+ case 20:
+
+ /* gp-relative instructions [major opcode 0x19] */
+
+ fieldA = 0;
+ fieldB = 26; /* Field B is the gp register */
+ fieldC = FIELDS_AC(state->words[0]);
+ switch (BITS(state->words[0],9,10))
+ {
+ case 0:
+ case 3:
+ fieldC = fieldC << 2; break;
+ case 2:
+ fieldC = fieldC << 1; break;
+ }
+ fieldCisReg = 0;
+
+ write_instr_name();
+
+ if (BITS(state->words[0],9,10) != 3)
+ {
+ WRITE_FORMAT_x_COMMA_LB(A);
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x_RB(C);
+ }
+ else
+ {
+ WRITE_FORMAT_x(A);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ }
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldA, fieldB, fieldC);
+ break;
+
+ case 21:
+
+ /* add/cmp/btst instructions [major opcode 28] */
+
+ FIELD_B_AC();
+ if (state->_opcode == op_Su5)
+ fieldC = (BITS(state->words[0],0,4));
+ else
+ fieldC = (BITS(state->words[0],0,6));
+ fieldCisReg = 0;
+ write_instr_name();
+
+ if (!BIT(state->words[0],7))
+ {
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldB, fieldC);
+ }
+ else
+ {
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ }
+ break;
+
+ case 22:
+
+ /* ARCompact 16-bit instructions, General ops/ single ops */
+
+ FIELD_C_AC();
+ FIELD_B_AC();
+
+ write_instr_name();
+
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldB, fieldC);
+ break;
+
+ case 23:
+
+ /* Shift/subtract/bit immediate instructions [major opcode 23] */
+
+ FIELD_B_AC();
+ fieldC = FIELDU_AC(state->words[0]);
+ fieldCisReg = 0;
+ write_instr_name();
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldB, fieldC);
+ break;
+
+ case 24:
+
+ /* ARCompact 16-bit Branch conditionally */
+
+ if (state->_opcode == op_BL_S)
+ {
+ fieldA = (BITS(state->words[0],0,10)) << 2;
+ fieldA = sign_extend(fieldA, 13);
+ }
+ else if (BITS(state->words[0],9,10) != 3)
+ {
+ fieldA = (BITS(state->words[0],0,8)) << 1;
+ fieldA = sign_extend(fieldA, 10);
+ }
+ else
+ {
+ fieldA = (BITS(state->words[0],0,5)) << 1;
+ fieldA = sign_extend(fieldA, 7);
+ }
+ fieldA += (addr & ~0x3);
+
+ write_instr_name();
+ /* This address could be a label we know. Convert it. */
+ add_target(fieldA); /* For debugger. */
+ state->flow = state->_opcode == op_BL_S /* BL */
+ ? direct_call
+ : direct_jump;
+ /* indirect calls are achieved by "lr blink,[status]; */
+ /* lr dest<- func addr; j [dest]" */
+
+ strcat(formatString, "%s"); /* address/label name */
+ my_sprintf(state, state->operandBuffer, formatString, post_address(state, fieldA));
+ write_comments();
+ break;
+
+ case 25:
+
+ /* ARCompact 16-bit Branch conditionally on reg z/nz */
+
+ FIELD_B_AC();
+ fieldC = (BITS(state->words[0],0,6)) << 1;
+ fieldC = sign_extend (fieldC, 8);
+
+ fieldC += (addr & ~0x3);
+ fieldA = fieldAisReg = fieldCisReg = 0;
+
+ write_instr_name();
+ /* This address could be a label we know. Convert it. */
+ add_target(fieldC); /* For debugger. */
+
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(A);
+ strcat(formatString, ",%s"); /* address/label name */
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldA, post_address(state, fieldC));
+ write_comments();
+ break;
+
+ case 26:
+
+ /* Zero operand Instructions */
+
+ write_instr_name();
+ state->operandBuffer[0] = '\0';
+ break;
+
+ case 27:
+
+ /* j_s instruction */
+
+ FIELD_B_AC ();
+ state->register_for_indirect_jump = fieldB;
+ write_instr_name ();
+ strcat (formatString,"[%r]");
+ my_sprintf (state, state->operandBuffer, formatString, fieldB);
+ break;
+
+ case 28:
+
+ /* Load/Store with offset */
+
+ FIELD_C_AC();
+ FIELD_B_AC();
+ switch (state->_opcode)
+ {
+ case op_LD_S :
+ case op_ST_S :
+ fieldA = (FIELDU_AC(state->words[0])) << 2;
+ break;
+ case op_LDB_S :
+ case op_STB_S :
+ fieldA = (FIELDU_AC(state->words[0]));
+ break;
+ case op_LDW_S :
+ case op_LDWX_S :
+ case op_STW_S :
+ fieldA = (FIELDU_AC(state->words[0])) << 1;
+ break;
+ }
+ fieldAisReg = 0;
+
+ write_instr_name();
+
+ WRITE_FORMAT_x_COMMA_LB(C);
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(A);
+ WRITE_FORMAT_RB();
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldC, fieldB, fieldA);
+ write_comments();
+ break;
+
+ case 29:
+
+ /* Load pc-relative */
+
+ FIELD_B_AC();
+ fieldC = 63;
+ fieldA = (BITS(state->words[0],0,7)) << 2;
+ fieldAisReg = 0;
+
+ write_instr_name();
+
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_FORMAT_COMMA_x(A);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC, fieldA);
+ write_comments();
+ break;
+
+ case 30:
+
+ /* mov immediate */
+
+ FIELD_B_AC();
+ fieldC = (BITS(state->words[0],0,7));
+ fieldCisReg = 0;
+
+ write_instr_name();
+
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ write_comments();
+ break;
+
+ case 31:
+
+ /* push/pop instructions */
+
+ if (BITS(state->words[0],0,4) == 1)
+ {
+ FIELD_B_AC();
+ }
+ else if (BITS(state->words[0],0,4) == 17)
+ fieldB = 31;
+
+ write_instr_name();
+
+ WRITE_FORMAT_x(B);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB);
+ break;
+
+ case 32:
+
+ /* Single operand instruction */
+
+ if (!BITS(state->words[0],22,23))
+ {
+ CHECK_FIELD_C();
+ }
+ else
+ {
+ FIELD_C();
+ fieldCisReg = 0;
+ }
+
+ write_instr_name();
+
+ if (!fieldC)
+ state->operandBuffer[0] = '\0';
+ else
+ {
+ WRITE_FORMAT_x(C);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldC);
+ }
+ break;
+
+ case 33:
+ /* For trap_s and the class of instructions that have
+ unsigned 6 bits in the fields B and C in A700 16 bit
+ instructions */
+ fieldC = FIELDC_AC(state->words[0]);
+ fieldB = FIELDB_AC(state->words[0]);
+ fieldCisReg = 0;
+ fieldBisReg = 0;
+ write_instr_name();
+ strcat(formatString,"%d");
+ my_sprintf(state,state->operandBuffer,formatString, ((fieldB << 3) | fieldC));
+ break;
+
+ case 34:
+ /* For ex.di and its class of instructions within op_major_4
+ This class is different from the normal set of instructions
+ in op_major_4 because this uses bit 15 as .di and the second
+ operand is actually a memory operand.
+ This is of the class
+ <op>.<di> b,[c] and <op>.<di> b,[limm]
+ */
+
+
+ /* field C is either a register or limm (different!) */
+
+ CHECK_FIELD_C();
+ FIELD_B();
+ directMem = BIT(state->words[0],15);
+
+
+ if (BITS(state->words[0],22,23) == 1 )
+ fieldCisReg = 0;
+ if (fieldCisReg)
+ state->ea_reg1 = fieldC;
+
+ write_instr_name();
+ WRITE_FORMAT_x_COMMA_LB(B);
+
+ WRITE_FORMAT_x_RB(C);
+
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ write_comments();
+ break;
+
+ case 35:
+
+ /* sub_s.ne instruction */
+
+ FIELD_B_AC();
+ write_instr_name();
+ strcat(formatString,"%r,%r,%r");
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldB, fieldB);
+ break;
+
+ case 36:
+
+ FIELD_B_AC();
+
+ write_instr_name();
+
+ WRITE_FORMAT_x(B);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state, state->operandBuffer, formatString, fieldB);
+
+ break;
+ /*******SIMD instructions decoding follows*************/
+ case 37:
+ case 39:
+ case 41:
+ /*fieldA is vr register
+ fieldB is I register
+ fieldC is a constant
+ %*,[%(,%<]
+ or
+ %*,%(,%<
+ or
+ %*,%(,%u
+ */
+
+ CHECK_FIELD_A();
+
+ CHECK_FIELD_B();
+ if (decodingClass == 41)
+ {
+ FIELD_C();
+ }
+ else
+ {
+ FIELD_U8();
+
+ if (simd_scale_u8>0)
+ fieldC = fieldC << simd_scale_u8;
+ }
+
+ fieldCisReg = 0;
+
+ write_instr_name();
+ (decodingClass == 37 ? WRITE_FORMAT_x_COMMA_LB(A) :
+ WRITE_FORMAT_x_COMMA(A));
+ WRITE_FORMAT_x_COMMA(B);
+ (decodingClass == 37 ? WRITE_FORMAT_x_RB(C):
+ WRITE_FORMAT_x(C));
+ WRITE_NOP_COMMENT();
+ my_sprintf(state,state->operandBuffer, formatString, fieldA, fieldB, fieldC);
+
+
+ break;
+ case 38:
+ /* fieldA is a vr register
+ fieldB is a ARC700 basecase register.
+ %*,[%b]
+ */
+ CHECK_FIELD_A();
+ CHECK_FIELD_B();
+
+ write_instr_name();
+ WRITE_FORMAT_x_COMMA_LB(A);
+ WRITE_FORMAT_x_RB(B);
+ WRITE_NOP_COMMENT();
+ my_sprintf(state,state->operandBuffer, formatString, fieldA, fieldB);
+
+ break;
+ case 40:
+ /* fieldB & fieldC are vr registers
+ %(,%)
+ or
+ %B,%C
+ or
+ %(,%C
+ */
+ CHECK_FIELD_B();
+ CHECK_FIELD_C();
+
+ write_instr_name();
+ WRITE_FORMAT_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ my_sprintf(state, state->operandBuffer, formatString, fieldB, fieldC);
+ break;
+
+ case 42:
+ /* fieldA, fieldB, fieldC are all vr registers
+ %*, %(, %) */
+ CHECK_FIELD_A();
+ CHECK_FIELD_B();
+ FIELD_C();
+
+ write_instr_name();
+ WRITE_FORMAT_x(A);
+ WRITE_FORMAT_COMMA_x(B);
+ WRITE_FORMAT_COMMA_x(C);
+ my_sprintf(state, state->operandBuffer, formatString, fieldA, fieldB, fieldC);
+ break;
+
+ case 43:
+ /* Only fieldC is a register
+ %C*/
+ CHECK_FIELD_C();
+
+ if (BITS(state->words[0], 17, 23) == 55)
+ fieldCisReg = 0;
+
+ write_instr_name();
+ WRITE_FORMAT_x(C);
+ my_sprintf(state, state->operandBuffer, formatString, fieldC);
+ break;
+
+ /***************SIMD decoding ends*********************/
+ default:
+ mwerror(state, "Bad decoding class in ARC disassembler");
+ break;
+ }
+
+ state->_cond = cond;
+ return state->instructionLen = offset;
+}
+
+
+/*
+ * _coreRegName - Returns the name the user specified core extension
+ * register.
+ */
+static const char *
+_coreRegName
+(
+ void *_this ATTRIBUTE_UNUSED, /* C++ this pointer */
+ int v /* Register value */
+ )
+{
+ return arcExtMap_coreRegName(v);
+}
+
+/*
+ * _auxRegName - Returns the name the user specified AUX extension
+ * register.
+ */
+static const char *
+_auxRegName
+( void *_this ATTRIBUTE_UNUSED, /* C++ this pointer */
+ int v /* Register value */
+ )
+{
+ return arcExtMap_auxRegName(v);
+}
+
+
+/*
+ * _condCodeName - Returns the name the user specified condition code
+ * name.
+ */
+static const char *
+_condCodeName
+(
+ void *_this ATTRIBUTE_UNUSED, /* C++ this pointer */
+ int v /* Register value */
+ )
+{
+ return arcExtMap_condCodeName(v);
+}
+
+
+/*
+ * _instName - Returns the name the user specified extension instruction.
+ */
+static const char *
+_instName
+(
+ void *_this ATTRIBUTE_UNUSED, /* C++ this pointer */
+ int op1, /* major opcode value */
+ int op2, /* minor opcode value */
+ int *flags /* instruction flags */
+ )
+{
+ return arcExtMap_instName(op1, op2, flags);
+}
+
+static void
+parse_disassembler_options (char *options)
+{
+ if (!strncasecmp (options, "simd",4))
+ {
+ enable_simd = 1;
+ }
+}
+
+/*
+ * This function is the same as decodeInstr except that this function
+ * returns a struct arcDisState instead of the instruction length.
+ *
+ * This struct contains information useful to the debugger.
+ */
+struct arcDisState
+arcAnalyzeInstr
+(
+ bfd_vma address, /* Address of this instruction */
+ disassemble_info* info
+ )
+{
+ int status;
+ bfd_byte buffer[4];
+ struct arcDisState s; /* ARC Disassembler state */
+ int lowbyte, highbyte;
+
+ lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
+ highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
+
+ memset (&s, 0, sizeof (struct arcDisState));
+
+ /* read first instruction */
+ status = (*info->read_memory_func) (address, buffer, 2, info);
+
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, address, info);
+ s.instructionLen = -1;
+ return s;
+ }
+
+ if ((buffer[lowbyte] & 0xf8) > 0x38)
+ {
+ info->bytes_per_line = 2;
+ s.words[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
+ status = (*info->read_memory_func) (address + 2, buffer, 4, info);
+ if (info->endian == BFD_ENDIAN_LITTLE)
+ s.words[1] = bfd_getl32 (buffer);
+ else
+ s.words[1] = bfd_getb32 (buffer);
+ }
+ else
+ {
+ info->bytes_per_line = 4;
+ status = (*info->read_memory_func) (address + 2, &buffer[2], 2, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, address + 2, info);
+ s.instructionLen = -1;
+ return s;
+ }
+ if (info->endian == BFD_ENDIAN_LITTLE)
+ s.words[0] = bfd_getl32(buffer);
+ else
+ s.words[0] = bfd_getb32(buffer);
+
+ /* Always read second word in case of limm. */
+ /* We ignore the result since the last insn may not have a limm. */
+ status = (*info->read_memory_func) (address + 4, buffer, 4, info);
+ if (info->endian == BFD_ENDIAN_LITTLE)
+ s.words[1] = bfd_getl32(buffer);
+ else
+ s.words[1] = bfd_getb32(buffer);
+ }
+
+ s._this = &s;
+ s.coreRegName = _coreRegName;
+ s.auxRegName = _auxRegName;
+ s.condCodeName = _condCodeName;
+ s.instName = _instName;
+
+ /* disassemble */
+ dsmOneArcInst (address, (void *)&s, info);
+
+ return s;
+}
+
+/* ARCompact_decodeInstr - Decode an ARCompact instruction returning the
+ size of the instruction in bytes or zero if unrecognized. */
+int
+ARCompact_decodeInstr (address, info)
+ bfd_vma address; /* Address of this instruction. */
+ disassemble_info* info;
+{
+ void *stream = info->stream; /* output stream */
+ fprintf_ftype func = info->fprintf_func;
+ char buf[256];
+
+ if (info->disassembler_options)
+ {
+ parse_disassembler_options (info->disassembler_options);
+
+ /* To avoid repeated parsing of these options, we remove them here. */
+ info->disassembler_options = NULL;
+ }
+
+ s = arcAnalyzeInstr (address, info);
+
+ if (!s.this)
+ return -1;
+
+ /* display the disassembly instruction */
+
+ if (s.instructionLen == 2)
+ (*func) (stream, " ");
+
+ (*func) (stream, "%08x ", s.words[0]);
+ (*func) (stream, " ");
+
+ (*func) (stream, "%-10s ", s.instrBuffer);
+
+ if (__TRANSLATION_REQUIRED(s))
+ {
+ bfd_vma addr;
+ char *tmpBuffer;
+ int i = 1;
+ if (s.operandBuffer[0] != '@')
+ {
+ /* Branch instruction with 3 operands, Translation is required
+ only for the third operand. Print the first 2 operands */
+ strcpy (buf, s.operandBuffer);
+ tmpBuffer = strtok (buf,"@");
+ (*func) (stream, "%s",tmpBuffer);
+ i = strlen (tmpBuffer)+1;
+ }
+ addr = s.addresses[s.operandBuffer[i] - '0'];
+ (*info->print_address_func) ((bfd_vma) addr, info);
+ (*func) (stream, "\n");
+ }
+ else
+ (*func) (stream, "%s",s.operandBuffer);
+ return s.instructionLen;
+
+}