return ((insn >> 10) & 0x1f) + 1;
}
+static unsigned
+insert_nps_bitop_size_2b (unsigned insn ATTRIBUTE_UNUSED,
+ int value ATTRIBUTE_UNUSED,
+ const char **errmsg ATTRIBUTE_UNUSED)
+{
+ switch (value)
+ {
+ case 1:
+ value = 0;
+ break;
+ case 2:
+ value = 1;
+ break;
+ case 4:
+ value = 2;
+ break;
+ case 8:
+ value = 3;
+ break;
+ default:
+ value = 0;
+ *errmsg = _("Invalid size, should be 1, 2, 4, or 8.");
+ break;
+ }
+
+ insn |= value << 10;
+ return insn;
+}
+
+static int
+extract_nps_bitop_size_2b (unsigned insn ATTRIBUTE_UNUSED,
+ bfd_boolean * invalid ATTRIBUTE_UNUSED)
+{
+ return 1 << ((insn >> 10) & 0x3);
+}
+
+static unsigned
+insert_nps_bitop_uimm8 (unsigned insn ATTRIBUTE_UNUSED,
+ int value ATTRIBUTE_UNUSED,
+ const char **errmsg ATTRIBUTE_UNUSED)
+{
+ insn |= ((value >> 5) & 7) << 12;
+ insn |= (value & 0x1f);
+ return insn;
+}
+
+static int
+extract_nps_bitop_uimm8 (unsigned insn ATTRIBUTE_UNUSED,
+ bfd_boolean * invalid ATTRIBUTE_UNUSED)
+{
+ return (((insn >> 12) & 0x7) << 5) | (insn & 0x1f);
+}
+
+static unsigned
+insert_nps_rflt_uimm6 (unsigned insn ATTRIBUTE_UNUSED,
+ int value ATTRIBUTE_UNUSED,
+ const char **errmsg ATTRIBUTE_UNUSED)
+{
+ switch (value)
+ {
+ case 1:
+ case 2:
+ case 4:
+ break;
+
+ default:
+ *errmsg = _("invalid immediate, must be 1, 2, or 4");
+ value = 0;
+ }
+
+ insn |= (value << 6);
+ return insn;
+}
+
+static int
+extract_nps_rflt_uimm6 (unsigned insn ATTRIBUTE_UNUSED,
+ bfd_boolean * invalid ATTRIBUTE_UNUSED)
+{
+ return (insn >> 6) & 0x3f;
+}
+
+static unsigned
+insert_nps_dst_pos_and_size (unsigned insn ATTRIBUTE_UNUSED,
+ int value ATTRIBUTE_UNUSED,
+ const char **errmsg ATTRIBUTE_UNUSED)
+{
+ insn |= ((value & 0x1f) | (((32 - value - 1) & 0x1f) << 10));
+ return insn;
+}
+
+static int
+extract_nps_dst_pos_and_size (unsigned insn ATTRIBUTE_UNUSED,
+ bfd_boolean * invalid ATTRIBUTE_UNUSED)
+{
+ return (insn & 0x1f);
+}
+
/* Include the generic extract/insert functions. Order is important
as some of the functions present in the .h may be disabled via
defines. */
#define F_NPS_FLAG (F_NPS_CL + 1)
{ "f", 1, 1, 20, 1 },
+
+#define F_NPS_R (F_NPS_FLAG + 1)
+ { "r", 1, 1, 15, 1 },
+
+#define F_NPS_RW (F_NPS_R + 1)
+ { "rw", 0, 1, 7, 1 },
+
+#define F_NPS_RD (F_NPS_RW + 1)
+ { "rd", 1, 1, 7, 1 },
+
+#define F_NPS_WFT (F_NPS_RD + 1)
+ { "wft", 0, 0, 0, 1 },
+
+#define F_NPS_IE1 (F_NPS_WFT + 1)
+ { "ie1", 1, 2, 8, 1 },
+
+#define F_NPS_IE2 (F_NPS_IE1 + 1)
+ { "ie2", 2, 2, 8, 1 },
+
+#define F_NPS_IE12 (F_NPS_IE2 + 1)
+ { "ie12", 3, 2, 8, 1 },
+
+#define F_NPS_SYNC_RD (F_NPS_IE12 + 1)
+ { "rd", 0, 1, 6, 1 },
+
+#define F_NPS_SYNC_WR (F_NPS_SYNC_RD + 1)
+ { "wr", 1, 1, 6, 1 },
+
+#define F_NPS_HWS_OFF (F_NPS_SYNC_WR + 1)
+ { "off", 0, 0, 0, 1 },
+
+#define F_NPS_HWS_RESTORE (F_NPS_HWS_OFF + 1)
+ { "restore", 0, 0, 0, 1 },
+
};
const unsigned arc_num_flag_operands = ARRAY_SIZE (arc_flag_operands);
{ F_CLASS_NONE, { F_NULL } },
#define C_CC (C_EMPTY + 1)
- { F_CLASS_OPTIONAL, { F_ALWAYS, F_RA, F_EQUAL, F_ZERO, F_NOTEQUAL,
- F_NOTZERO, F_POZITIVE, F_PL, F_NEGATIVE, F_MINUS,
- F_CARRY, F_CARRYSET, F_LOWER, F_CARRYCLR,
- F_NOTCARRY, F_HIGHER, F_OVERFLOWSET, F_OVERFLOW,
- F_NOTOVERFLOW, F_OVERFLOWCLR, F_GT, F_GE, F_LT,
- F_LE, F_HI, F_LS, F_PNZ, F_NULL } },
+ { F_CLASS_OPTIONAL | F_CLASS_EXTEND,
+ { F_ALWAYS, F_RA, F_EQUAL, F_ZERO, F_NOTEQUAL,
+ F_NOTZERO, F_POZITIVE, F_PL, F_NEGATIVE, F_MINUS,
+ F_CARRY, F_CARRYSET, F_LOWER, F_CARRYCLR,
+ F_NOTCARRY, F_HIGHER, F_OVERFLOWSET, F_OVERFLOW,
+ F_NOTOVERFLOW, F_OVERFLOWCLR, F_GT, F_GE, F_LT,
+ F_LE, F_HI, F_LS, F_PNZ, F_NULL } },
#define C_AA_ADDR3 (C_CC + 1)
#define C_AA27 (C_CC + 1)
#define C_NPS_F (C_NPS_CL + 1)
{ F_CLASS_OPTIONAL, { F_NPS_FLAG, F_NULL}},
+
+#define C_NPS_R (C_NPS_F + 1)
+ { F_CLASS_OPTIONAL, { F_NPS_R, F_NULL}},
+
+#define C_NPS_SCHD_RW (C_NPS_R + 1)
+ { F_CLASS_REQUIRED, { F_NPS_RW, F_NPS_RD, F_NULL}},
+
+#define C_NPS_SCHD_TRIG (C_NPS_SCHD_RW + 1)
+ { F_CLASS_REQUIRED, { F_NPS_WFT, F_NULL}},
+
+#define C_NPS_SCHD_IE (C_NPS_SCHD_TRIG + 1)
+ { F_CLASS_OPTIONAL, { F_NPS_IE1, F_NPS_IE2, F_NPS_IE12, F_NULL}},
+
+#define C_NPS_SYNC (C_NPS_SCHD_IE + 1)
+ { F_CLASS_REQUIRED, { F_NPS_SYNC_RD, F_NPS_SYNC_WR, F_NULL}},
+
+#define C_NPS_HWS_OFF (C_NPS_SYNC + 1)
+ { F_CLASS_REQUIRED, { F_NPS_HWS_OFF, F_NULL}},
+
+#define C_NPS_HWS_RESTORE (C_NPS_HWS_OFF + 1)
+ { F_CLASS_REQUIRED, { F_NPS_HWS_RESTORE, F_NULL}},
+
};
+const unsigned char flags_none[] = { 0 };
+const unsigned char flags_f[] = { C_F };
+const unsigned char flags_cc[] = { C_CC };
+const unsigned char flags_ccf[] = { C_CC, C_F };
+
/* The operands table.
The format of the operands table is:
#define R3 (R2 + 1)
#define R3_S (R2 + 1)
{ 2, 0, 0, ARC_OPERAND_IR, insert_r3, extract_r3 },
-#define SP (R3 + 1)
+#define RSP (R3 + 1)
#define SP_S (R3 + 1)
{ 5, 0, 0, ARC_OPERAND_IR, insert_sp, extract_sp },
-#define SPdup (SP + 1)
-#define SP_Sdup (SP + 1)
+#define SPdup (RSP + 1)
+#define SP_Sdup (RSP + 1)
{ 5, 0, 0, ARC_OPERAND_IR | ARC_OPERAND_DUPLICATE, insert_sp, extract_sp },
#define GP (SPdup + 1)
#define GP_S (SPdup + 1)
{ 3, 21, 0, ARC_OPERAND_IR | ARC_OPERAND_NCHK, insert_nps_3bit_src2, extract_nps_3bit_src2 },
#define NPS_R_DST (NPS_R_SRC2_3B + 1)
- { 6, 21, 0, ARC_OPERAND_IR | ARC_OPERAND_NCHK, NULL, NULL },
+ { 6, 21, 0, ARC_OPERAND_IR, NULL, NULL },
#define NPS_R_SRC1 (NPS_R_DST + 1)
- { 6, 21, 0, ARC_OPERAND_IR | ARC_OPERAND_DUPLICATE | ARC_OPERAND_NCHK, NULL, NULL },
+ { 6, 21, 0, ARC_OPERAND_IR | ARC_OPERAND_DUPLICATE, NULL, NULL },
#define NPS_BITOP_DST_POS (NPS_R_SRC1 + 1)
{ 5, 5, 0, ARC_OPERAND_UNSIGNED, 0, 0 },
{ 5, 0, 0, ARC_OPERAND_UNSIGNED, 0, 0 },
#define NPS_BITOP_SIZE (NPS_BITOP_SRC_POS + 1)
- { 5, 10, 0, ARC_OPERAND_UNSIGNED, insert_nps_bitop_size, extract_nps_bitop_size },
+ { 5, 10, 0, ARC_OPERAND_UNSIGNED | ARC_OPERAND_NCHK, insert_nps_bitop_size, extract_nps_bitop_size },
+
+#define NPS_BITOP_DST_POS_SZ (NPS_BITOP_SIZE + 1)
+ { 5, 0, 0, ARC_OPERAND_UNSIGNED, insert_nps_dst_pos_and_size, extract_nps_dst_pos_and_size },
+
+#define NPS_BITOP_SIZE_2B (NPS_BITOP_DST_POS_SZ + 1)
+ { 0, 0, 0, ARC_OPERAND_UNSIGNED | ARC_OPERAND_NCHK, insert_nps_bitop_size_2b, extract_nps_bitop_size_2b },
-#define NPS_UIMM16 (NPS_BITOP_SIZE + 1)
+#define NPS_BITOP_UIMM8 (NPS_BITOP_SIZE_2B + 1)
+ { 8, 0, 0, ARC_OPERAND_UNSIGNED, insert_nps_bitop_uimm8, extract_nps_bitop_uimm8 },
+
+#define NPS_UIMM16 (NPS_BITOP_UIMM8 + 1)
{ 16, 0, 0, ARC_OPERAND_UNSIGNED, NULL, NULL },
+
+#define NPS_RFLT_UIMM6 (NPS_UIMM16 + 1)
+ { 6, 6, 0, ARC_OPERAND_UNSIGNED | ARC_OPERAND_NCHK, insert_nps_rflt_uimm6, extract_nps_rflt_uimm6 },
};
const unsigned arc_num_operands = ARRAY_SIZE (arc_operands);
const unsigned arc_Toperand = FKT_T;
const unsigned arc_NToperand = FKT_NT;
+const unsigned char arg_none[] = { 0 };
+const unsigned char arg_32bit_rarbrc[] = { RA, RB, RC };
+const unsigned char arg_32bit_zarbrc[] = { ZA, RB, RC };
+const unsigned char arg_32bit_rbrbrc[] = { RB, RBdup, RC };
+const unsigned char arg_32bit_rarbu6[] = { RA, RB, UIMM6_20 };
+const unsigned char arg_32bit_zarbu6[] = { ZA, RB, UIMM6_20 };
+const unsigned char arg_32bit_rbrbu6[] = { RB, RBdup, UIMM6_20 };
+const unsigned char arg_32bit_rbrbs12[] = { RB, RBdup, SIMM12_20 };
+const unsigned char arg_32bit_ralimmrc[] = { RA, LIMM, RC };
+const unsigned char arg_32bit_rarblimm[] = { RA, RB, LIMM };
+const unsigned char arg_32bit_zalimmrc[] = { ZA, LIMM, RC };
+const unsigned char arg_32bit_zarblimm[] = { ZA, RB, LIMM };
+
+const unsigned char arg_32bit_rbrblimm[] = { RB, RBdup, LIMM };
+const unsigned char arg_32bit_ralimmu6[] = { RA, LIMM, UIMM6_20 };
+const unsigned char arg_32bit_zalimmu6[] = { ZA, LIMM, UIMM6_20 };
+
+const unsigned char arg_32bit_zalimms12[] = { ZA, LIMM, SIMM12_20 };
+const unsigned char arg_32bit_ralimmlimm[] = { RA, LIMM, LIMMdup };
+const unsigned char arg_32bit_zalimmlimm[] = { ZA, LIMM, LIMMdup };
+
+const unsigned char arg_32bit_rbrc[] = { RB, RC };
+const unsigned char arg_32bit_zarc[] = { ZA, RC };
+const unsigned char arg_32bit_rbu6[] = { RB, UIMM6_20 };
+const unsigned char arg_32bit_zau6[] = { ZA, UIMM6_20 };
+const unsigned char arg_32bit_rblimm[] = { RB, LIMM };
+const unsigned char arg_32bit_zalimm[] = { ZA, LIMM };
+
+const unsigned char arg_32bit_limmrc[] = { LIMM, RC };
+const unsigned char arg_32bit_limmu6[] = { LIMM, UIMM6_20 };
+const unsigned char arg_32bit_limms12[] = { LIMM, SIMM12_20 };
+const unsigned char arg_32bit_limmlimm[] = { LIMM, LIMMdup };
+
/* The opcode table.
The format of the opcode table is:
- NAME OPCODE MASK CPU CLASS SUBCLASS { OPERANDS } { FLAGS }. */
+ NAME OPCODE MASK CPU CLASS SUBCLASS { OPERANDS } { FLAGS }.
+
+ The table is organised such that, where possible, all instructions with
+ the same mnemonic are together in a block. When the assembler searches
+ for a suitable instruction the entries are checked in table order, so
+ more specific, or specialised cases should appear earlier in the table.
+
+ As an example, consider two instructions 'add a,b,u6' and 'add
+ a,b,limm'. The first takes a 6-bit immediate that is encoded within the
+ 32-bit instruction, while the second takes a 32-bit immediate that is
+ encoded in a follow-on 32-bit, making the total instruction length
+ 64-bits. In this case the u6 variant must appear first in the table, as
+ all u6 immediates could also be encoded using the 'limm' extension,
+ however, we want to use the shorter instruction wherever possible.
+
+ It is possible though to split instructions with the same mnemonic into
+ multiple groups. However, the instructions are still checked in table
+ order, even across groups. The only time that instructions with the
+ same mnemonic should be split into different groups is when different
+ variants of the instruction appear in different architectures, in which
+ case, grouping all instructions from a particular architecture together
+ might be preferable to merging the instruction into the main instruction
+ table.
+
+ An example of this split instruction groups can be found with the 'sync'
+ instruction. The core arc architecture provides a 'sync' instruction,
+ while the nps instruction set extension provides 'sync.rd' and
+ 'sync.wr'. The rd/wr flags are instruction flags, not part of the
+ mnemonic, so we end up with two groups for the sync instruction, the
+ first within the core arc instruction table, and the second within the
+ nps extension instructions. */
const struct arc_opcode arc_opcodes[] =
{
#include "arc-tbl.h"
#include "arc-nps400-tbl.h"
-};
+#include "arc-ext-tbl.h"
-const unsigned arc_num_opcodes = ARRAY_SIZE (arc_opcodes);
+ { NULL, 0, 0, 0, 0, 0, { 0 }, { 0 } }
+};
/* List with special cases instructions and the applicable flags. */
const struct arc_flag_special arc_flag_special_cases[] =
const struct arc_aux_reg arc_aux_regs[] =
{
#undef DEF
-#define DEF(ADDR, NAME) \
- { ADDR, #NAME, sizeof (#NAME)-1 },
+#define DEF(ADDR, CPU, SUBCLASS, NAME) \
+ { ADDR, CPU, SUBCLASS, #NAME, sizeof (#NAME)-1 },
#include "arc-regs.h"