+
+/* Debug function used to dump the ARC information fount in arcextmap
+ sections. */
+
+void
+dump_ARC_extmap (void)
+{
+ struct ExtAuxRegister *r;
+ int i;
+
+ r = arc_extension_map.auxRegisters;
+
+ while (r)
+ {
+ printf ("AUX : %s %u\n", r->name, r->address);
+ r = r->next;
+ }
+
+ for (i = 0; i < INST_HASH_SIZE; i++)
+ {
+ struct ExtInstruction *insn;
+
+ for (insn = arc_extension_map.instructions[i];
+ insn != NULL; insn = insn->next)
+ {
+ printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
+ switch (insn->flags & ARC_SYNTAX_MASK)
+ {
+ case ARC_SYNTAX_2OP:
+ printf ("SYNTAX_2OP");
+ break;
+ case ARC_SYNTAX_3OP:
+ printf ("SYNTAX_3OP");
+ break;
+ case ARC_SYNTAX_1OP:
+ printf ("SYNTAX_1OP");
+ break;
+ case ARC_SYNTAX_NOP:
+ printf ("SYNTAX_NOP");
+ break;
+ default:
+ printf ("SYNTAX_UNK");
+ break;
+ }
+
+ if (insn->flags & 0x10)
+ printf ("|MODIFIER");
+
+ printf (" %s\n", insn->name);
+ }
+ }
+
+ for (i = 0; i < NUM_EXT_CORE; i++)
+ {
+ struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
+
+ if (reg.name)
+ printf ("CORE: 0x%04x %s %s\n", reg.number,
+ ExtReadWrite_image (reg.rw),
+ reg.name);
+ }
+
+ for (i = 0; i < NUM_EXT_COND; i++)
+ if (arc_extension_map.condCodes[i])
+ printf ("COND: %s\n", arc_extension_map.condCodes[i]);
+}
+
+/* For a given extension instruction generate the equivalent arc
+ opcode structure. */
+
+struct arc_opcode *
+arcExtMap_genOpcode (const extInstruction_t *einsn,
+ unsigned arc_target,
+ const char **errmsg)
+{
+ struct arc_opcode *q, *arc_ext_opcodes = NULL;
+ const unsigned char *lflags_f;
+ const unsigned char *lflags_ccf;
+ int count;
+
+ /* Check for the class to see how many instructions we generate. */
+ switch (einsn->flags & ARC_SYNTAX_MASK)
+ {
+ case ARC_SYNTAX_3OP:
+ count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
+ break;
+ case ARC_SYNTAX_2OP:
+ count = (einsn->flags & 0x10) ? 7 : 6;
+ break;
+ case ARC_SYNTAX_1OP:
+ count = 3;
+ break;
+ case ARC_SYNTAX_NOP:
+ count = 1;
+ break;
+ default:
+ count = 0;
+ break;
+ }
+
+ /* Allocate memory. */
+ arc_ext_opcodes = (struct arc_opcode *)
+ xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
+
+ if (arc_ext_opcodes == NULL)
+ {
+ *errmsg = "Virtual memory exhausted";
+ return NULL;
+ }
+
+ /* Generate the patterns. */
+ q = arc_ext_opcodes;
+
+ if (einsn->suffix)
+ {
+ lflags_f = flags_none;
+ lflags_ccf = flags_none;
+ }
+ else
+ {
+ lflags_f = flags_f;
+ lflags_ccf = flags_ccf;
+ }
+
+ if (einsn->suffix & ARC_SUFFIX_COND)
+ lflags_ccf = flags_cc;
+ if (einsn->suffix & ARC_SUFFIX_FLAG)
+ {
+ lflags_f = flags_f;
+ lflags_ccf = flags_f;
+ }
+ if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
+ lflags_ccf = flags_ccf;
+
+ if (einsn->flags & ARC_SYNTAX_2OP
+ && !(einsn->flags & 0x10))
+ {
+ /* Regular 2OP instruction. */
+ if (einsn->suffix & ARC_SUFFIX_COND)
+ *errmsg = "Suffix SUFFIX_COND ignored";
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
+ arc_target, arg_32bit_rbrc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
+ arc_target, arg_32bit_zarc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
+ arc_target, arg_32bit_rbu6, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
+ arc_target, arg_32bit_zau6, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
+ arc_target, arg_32bit_rblimm, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
+ arc_target, arg_32bit_zalimm, lflags_f);
+ }
+ else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
+ {
+ /* This is actually a 3OP pattern. The first operand is
+ immplied and is set to zero. */
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
+ arc_target, arg_32bit_rbrc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
+ arc_target, arg_32bit_rbu6, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
+ arc_target, arg_32bit_rblimm, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
+ arc_target, arg_32bit_limmrc, lflags_ccf);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
+ arc_target, arg_32bit_limmu6, lflags_ccf);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
+ arc_target, arg_32bit_limms12, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
+ arc_target, arg_32bit_limmlimm, lflags_ccf);
+ }
+ else if (einsn->flags & ARC_SYNTAX_3OP
+ && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
+ {
+ /* Regular 3OP instruction. */
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_ABC (einsn->major, einsn->minor), MINSN3OP_ABC,
+ arc_target, arg_32bit_rarbrc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
+ arc_target, arg_32bit_zarbrc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
+ arc_target, arg_32bit_rbrbrc, lflags_ccf);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_ABU (einsn->major, einsn->minor), MINSN3OP_ABU,
+ arc_target, arg_32bit_rarbu6, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
+ arc_target, arg_32bit_zarbu6, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
+ arc_target, arg_32bit_rbrbu6, lflags_ccf);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_BBS (einsn->major, einsn->minor), MINSN3OP_BBS,
+ arc_target, arg_32bit_rbrbs12, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_ALC (einsn->major, einsn->minor), MINSN3OP_ALC,
+ arc_target, arg_32bit_ralimmrc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_ABL (einsn->major, einsn->minor), MINSN3OP_ABL,
+ arc_target, arg_32bit_rarblimm, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC,
+ arc_target, arg_32bit_zalimmrc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
+ arc_target, arg_32bit_zarblimm, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
+ arc_target, arg_32bit_zalimmrc, lflags_ccf);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
+ arc_target, arg_32bit_rbrblimm, lflags_ccf);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_ALU (einsn->major, einsn->minor), MINSN3OP_ALU,
+ arc_target, arg_32bit_ralimmu6, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU,
+ arc_target, arg_32bit_zalimmu6, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
+ arc_target, arg_32bit_zalimmu6, lflags_ccf);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
+ arc_target, arg_32bit_zalimms12, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_ALL (einsn->major, einsn->minor), MINSN3OP_ALL,
+ arc_target, arg_32bit_ralimmlimm, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL,
+ arc_target, arg_32bit_zalimmlimm, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
+ arc_target, arg_32bit_zalimmlimm, lflags_ccf);
+ }
+ else if (einsn->flags & ARC_SYNTAX_3OP)
+ {
+ /* 3OP instruction which accepts only zero as first
+ argument. */
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
+ arc_target, arg_32bit_zarbrc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
+ arc_target, arg_32bit_zarbu6, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC,
+ arc_target, arg_32bit_zalimmrc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
+ arc_target, arg_32bit_zarblimm, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
+ arc_target, arg_32bit_zalimmrc, lflags_ccf);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU,
+ arc_target, arg_32bit_zalimmu6, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
+ arc_target, arg_32bit_zalimmu6, lflags_ccf);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
+ arc_target, arg_32bit_zalimms12, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL,
+ arc_target, arg_32bit_zalimmlimm, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
+ arc_target, arg_32bit_zalimmlimm, lflags_ccf);
+ }
+ else if (einsn->flags & ARC_SYNTAX_1OP)
+ {
+ if (einsn->suffix & ARC_SUFFIX_COND)
+ *errmsg = "Suffix SUFFIX_COND ignored";
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor),
+ MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
+ | (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6,
+ lflags_f);
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
+ | FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm,
+ lflags_f);
+
+ }
+ else if (einsn->flags & ARC_SYNTAX_NOP)
+ {
+ if (einsn->suffix & ARC_SUFFIX_COND)
+ *errmsg = "Suffix SUFFIX_COND ignored";
+
+ INSERT_XOP (q, einsn->name,
+ INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
+ | (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f);
+ }
+ else
+ {
+ *errmsg = "Unknown syntax";
+ return NULL;
+ }
+
+ /* End marker. */
+ memset (q, 0, sizeof (*arc_ext_opcodes));
+
+ return arc_ext_opcodes;
+}