1 /* ARC target-dependent stuff.  Extension structure access functions
2    Copyright (C) 1995-2024 Free Software Foundation, Inc.
3 
4    This file is part of libopcodes.
5 
6    This library is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    It is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 #include "sysdep.h"
22 #include <stdlib.h>
23 #include <stdio.h>
24 
25 #include "bfd.h"
26 #include "arc-ext.h"
27 #include "elf/arc.h"
28 #include "libiberty.h"
29 
30 /* This module provides support for extensions to the ARC processor
31    architecture.  */
32 
33 
34 /* Local constants.  */
35 
36 #define FIRST_EXTENSION_CORE_REGISTER   32
37 #define LAST_EXTENSION_CORE_REGISTER    59
38 #define FIRST_EXTENSION_CONDITION_CODE  0x10
39 #define LAST_EXTENSION_CONDITION_CODE   0x1f
40 
41 #define NUM_EXT_CORE      \
42   (LAST_EXTENSION_CORE_REGISTER  - FIRST_EXTENSION_CORE_REGISTER  + 1)
43 #define NUM_EXT_COND      \
44   (LAST_EXTENSION_CONDITION_CODE - FIRST_EXTENSION_CONDITION_CODE + 1)
45 #define INST_HASH_BITS    6
46 #define INST_HASH_SIZE    (1 << INST_HASH_BITS)
47 #define INST_HASH_MASK    (INST_HASH_SIZE - 1)
48 
49 
50 /* Local types.  */
51 
52 /* These types define the information stored in the table.  */
53 
54 struct ExtAuxRegister
55 {
56   unsigned                      address;
57   char *              name;
58   struct ExtAuxRegister * next;
59 };
60 
61 struct ExtCoreRegister
62 {
63   short                 number;
64   enum ExtReadWrite rw;
65   char *      name;
66 };
67 
68 struct arcExtMap
69 {
70   struct ExtAuxRegister* auxRegisters;
71   struct ExtInstruction* instructions[INST_HASH_SIZE];
72   struct ExtCoreRegister coreRegisters[NUM_EXT_CORE];
73   char *             condCodes[NUM_EXT_COND];
74 };
75 
76 
77 /* Local data.  */
78 
79 /* Extension table.  */
80 static struct arcExtMap arc_extension_map;
81 
82 
83 /* Local macros.  */
84 
85 /* A hash function used to map instructions into the table.  */
86 #define INST_HASH(MAJOR, MINOR)    ((((MAJOR) << 3) ^ (MINOR)) & INST_HASH_MASK)
87 
88 
89 /* Local functions.  */
90 
91 static void
create_map(unsigned char * block,unsigned long length)92 create_map (unsigned char *block,
93               unsigned long length)
94 {
95   unsigned char *p = block;
96 
97   while (p && p < (block + length))
98     {
99       /* p[0] == length of record
100            p[1] == type of record
101            For instructions:
102              p[2]  = opcode
103              p[3]  = minor opcode (if opcode == 3)
104              p[4]  = flags
105              p[5]+ = name
106            For core regs and condition codes:
107              p[2]  = value
108              p[3]+ = name
109            For auxiliary regs:
110              p[2..5] = value
111              p[6]+   = name
112                (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]).  */
113 
114       /* The sequence of records is temrinated by an "empty"
115            record.  */
116       if (p[0] == 0)
117           break;
118 
119       switch (p[1])
120           {
121           case EXT_INSTRUCTION:
122             {
123               struct ExtInstruction  *insn = XNEW (struct ExtInstruction);
124               int                           major = p[2];
125               int                           minor = p[3];
126               struct ExtInstruction **bucket =
127                        &arc_extension_map.instructions[INST_HASH (major, minor)];
128 
129               insn->name  = xstrdup ((char *) (p + 5));
130               insn->major = major;
131               insn->minor = minor;
132               insn->flags = p[4];
133               insn->next  = *bucket;
134               insn->suffix = 0;
135               insn->syntax = 0;
136               insn->modsyn = 0;
137               *bucket = insn;
138               break;
139             }
140 
141           case EXT_CORE_REGISTER:
142             {
143               unsigned char number = p[2];
144               char*   name     = (char *) (p + 3);
145 
146               arc_extension_map.
147                 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
148                 = number;
149               arc_extension_map.
150                 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
151                 = REG_READWRITE;
152               arc_extension_map.
153                 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
154                 = xstrdup (name);
155               break;
156             }
157 
158           case EXT_LONG_CORE_REGISTER:
159             {
160               unsigned char     number = p[2];
161               char*       name   = (char *) (p + 7);
162               enum ExtReadWrite rw     = p[6];
163 
164               arc_extension_map.
165                 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
166                 = number;
167               arc_extension_map.
168                 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
169                 = rw;
170               arc_extension_map.
171                 coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
172                 = xstrdup (name);
173               break;
174             }
175 
176           case EXT_COND_CODE:
177             {
178               char *cc_name = xstrdup ((char *) (p + 3));
179 
180               arc_extension_map.
181                 condCodes[p[2] - FIRST_EXTENSION_CONDITION_CODE]
182                 = cc_name;
183               break;
184             }
185 
186           case EXT_AUX_REGISTER:
187             {
188               /* Trickier -- need to store linked list of these.  */
189               struct ExtAuxRegister *newAuxRegister
190                 = XNEW (struct ExtAuxRegister);
191               char *aux_name = xstrdup ((char *) (p + 6));
192 
193               newAuxRegister->name = aux_name;
194               newAuxRegister->address = (((unsigned) p[2] << 24) | (p[3] << 16)
195                                                | (p[4] << 8) | p[5]);
196               newAuxRegister->next = arc_extension_map.auxRegisters;
197               arc_extension_map.auxRegisters = newAuxRegister;
198               break;
199             }
200 
201           default:
202             break;
203           }
204 
205       p += p[0]; /* Move on to next record.  */
206     }
207 }
208 
209 
210 /* Free memory that has been allocated for the extensions.  */
211 
212 static void
destroy_map(void)213 destroy_map (void)
214 {
215   struct ExtAuxRegister *r;
216   unsigned int                 i;
217 
218   /* Free auxiliary registers.  */
219   r = arc_extension_map.auxRegisters;
220   while (r)
221     {
222       /* N.B. after r has been freed, r->next is invalid!  */
223       struct ExtAuxRegister* next = r->next;
224 
225       free (r->name);
226       free (r);
227       r = next;
228     }
229 
230   /* Free instructions.  */
231   for (i = 0; i < INST_HASH_SIZE; i++)
232     {
233       struct ExtInstruction *insn = arc_extension_map.instructions[i];
234 
235       while (insn)
236           {
237             /* N.B. after insn has been freed, insn->next is invalid!  */
238             struct ExtInstruction *next = insn->next;
239 
240             free (insn->name);
241             free (insn);
242             insn = next;
243           }
244     }
245 
246   /* Free core registers.  */
247   for (i = 0; i < NUM_EXT_CORE; i++)
248     free (arc_extension_map.coreRegisters[i].name);
249 
250   /* Free condition codes.  */
251   for (i = 0; i < NUM_EXT_COND; i++)
252     free (arc_extension_map.condCodes[i]);
253 
254   memset (&arc_extension_map, 0, sizeof (arc_extension_map));
255 }
256 
257 
258 static const char *
ExtReadWrite_image(enum ExtReadWrite val)259 ExtReadWrite_image (enum ExtReadWrite val)
260 {
261     switch (val)
262     {
263           case REG_INVALID  : return "INVALID";
264           case REG_READ         : return "RO";
265           case REG_WRITE        : return "WO";
266           case REG_READWRITE: return "R/W";
267           default               : return "???";
268     }
269 }
270 
271 
272 /* Externally visible functions.  */
273 
274 /* Get the name of an extension instruction.  */
275 
276 const extInstruction_t *
arcExtMap_insn(int opcode,unsigned long long insn)277 arcExtMap_insn (int opcode, unsigned long long insn)
278 {
279   /* Here the following tasks need to be done.  First of all, the
280      opcode stored in the Extension Map is the real opcode.  However,
281      the subopcode stored in the instruction to be disassembled is
282      mangled.  We pass (in minor opcode), the instruction word.  Here
283      we will un-mangle it and get the real subopcode which we can look
284      for in the Extension Map.  This function is used both for the
285      ARCTangent and the ARCompact, so we would also need some sort of
286      a way to distinguish between the two architectures.  This is
287      because the ARCTangent does not do any of this mangling so we
288      have no issues there.  */
289 
290   /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI.  If it is 1
291      then use iiiiIi.  Now, if P is 3 then check M[5:5] and if it is 0
292      then un-mangle using iiiiiI else iiiiii.  */
293 
294   unsigned char minor;
295   extInstruction_t *temp;
296 
297   /* 16-bit instructions.  */
298   if (0x08 <= opcode && opcode <= 0x0b)
299     {
300       unsigned char b, c, i;
301 
302       b = (insn & 0x0700) >> 8;
303       c = (insn & 0x00e0) >> 5;
304       i = (insn & 0x001f);
305 
306       if (i)
307           minor = i;
308       else
309           minor = (c == 0x07) ? b : c;
310     }
311   /* 32-bit instructions.  */
312   else
313     {
314       unsigned char I, A, B;
315 
316       I = (insn & 0x003f0000) >> 16;
317       A = (insn & 0x0000003f);
318       B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
319 
320       if (I != 0x2f)
321           {
322 #ifndef UNMANGLED
323             switch (P)
324               {
325               case 3:
326                 if (M)
327                     {
328                       minor = I;
329                       break;
330                     }
331               case 0:
332               case 2:
333                 minor = (I >> 1) | ((I & 0x1) << 5);
334                 break;
335               case 1:
336                 minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4);
337               }
338 #else
339             minor = I;
340 #endif
341           }
342       else
343           {
344             if (A != 0x3f)
345               minor = A;
346             else
347               minor = B;
348           }
349     }
350 
351   temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
352   while (temp)
353     {
354       if ((temp->major == opcode) && (temp->minor == minor))
355           {
356             return temp;
357           }
358       temp = temp->next;
359     }
360 
361   return NULL;
362 }
363 
364 /* Get the name of an extension core register.  */
365 
366 const char *
arcExtMap_coreRegName(int regnum)367 arcExtMap_coreRegName (int regnum)
368 {
369   if (regnum < FIRST_EXTENSION_CORE_REGISTER
370       || regnum > LAST_EXTENSION_CORE_REGISTER)
371     return NULL;
372   return arc_extension_map.
373     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name;
374 }
375 
376 /* Get the access mode of an extension core register.  */
377 
378 enum ExtReadWrite
arcExtMap_coreReadWrite(int regnum)379 arcExtMap_coreReadWrite (int regnum)
380 {
381   if (regnum < FIRST_EXTENSION_CORE_REGISTER
382       || regnum > LAST_EXTENSION_CORE_REGISTER)
383     return REG_INVALID;
384   return arc_extension_map.
385     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw;
386 }
387 
388 /* Get the name of an extension condition code.  */
389 
390 const char *
arcExtMap_condCodeName(int code)391 arcExtMap_condCodeName (int code)
392 {
393   if (code < FIRST_EXTENSION_CONDITION_CODE
394       || code > LAST_EXTENSION_CONDITION_CODE)
395     return NULL;
396   return arc_extension_map.
397     condCodes[code - FIRST_EXTENSION_CONDITION_CODE];
398 }
399 
400 /* Get the name of an extension auxiliary register.  */
401 
402 const char *
arcExtMap_auxRegName(unsigned address)403 arcExtMap_auxRegName (unsigned address)
404 {
405   /* Walk the list of auxiliary register names and find the name.  */
406   struct ExtAuxRegister *r;
407 
408   for (r = arc_extension_map.auxRegisters; r; r = r->next)
409     {
410       if (r->address == address)
411           return (const char *)r->name;
412     }
413   return NULL;
414 }
415 
416 /* Load extensions described in .arcextmap and
417    .gnu.linkonce.arcextmap.* ELF section.  */
418 
419 void
build_ARC_extmap(bfd * text_bfd)420 build_ARC_extmap (bfd *text_bfd)
421 {
422   asection *sect;
423 
424   /* The map is built each time gdb loads an executable file - so free
425      any existing map, as the map defined by the new file may differ
426      from the old.  */
427   destroy_map ();
428 
429   for (sect = text_bfd->sections; sect != NULL; sect = sect->next)
430     if (!strncmp (sect->name,
431                       ".gnu.linkonce.arcextmap.",
432             sizeof (".gnu.linkonce.arcextmap.") - 1)
433           || !strcmp (sect->name,".arcextmap"))
434       {
435           bfd_size_type  count  = bfd_section_size (sect);
436           unsigned char* buffer = xmalloc (count);
437 
438           if (buffer)
439             {
440               if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count))
441                 create_map (buffer, count);
442               free (buffer);
443             }
444       }
445 }
446 
447 /* Debug function used to dump the ARC information fount in arcextmap
448    sections.  */
449 
450 void
dump_ARC_extmap(void)451 dump_ARC_extmap (void)
452 {
453     struct ExtAuxRegister *r;
454     int                          i;
455 
456     r = arc_extension_map.auxRegisters;
457 
458     while (r)
459     {
460           printf ("AUX : %s %u\n", r->name, r->address);
461           r = r->next;
462     }
463 
464     for (i = 0; i < INST_HASH_SIZE; i++)
465     {
466           struct ExtInstruction *insn;
467 
468           for (insn = arc_extension_map.instructions[i];
469                insn != NULL; insn = insn->next)
470             {
471               printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
472               switch (insn->flags & ARC_SYNTAX_MASK)
473                 {
474                 case ARC_SYNTAX_2OP:
475                     printf ("SYNTAX_2OP");
476                     break;
477                 case ARC_SYNTAX_3OP:
478                     printf ("SYNTAX_3OP");
479                     break;
480                 case ARC_SYNTAX_1OP:
481                     printf ("SYNTAX_1OP");
482                     break;
483                 case ARC_SYNTAX_NOP:
484                     printf ("SYNTAX_NOP");
485                     break;
486                 default:
487                     printf ("SYNTAX_UNK");
488                     break;
489                 }
490 
491               if (insn->flags & 0x10)
492                 printf ("|MODIFIER");
493 
494               printf (" %s\n", insn->name);
495             }
496     }
497 
498     for (i = 0; i < NUM_EXT_CORE; i++)
499     {
500           struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
501 
502           if (reg.name)
503             printf ("CORE: 0x%04x %s %s\n", reg.number,
504                       ExtReadWrite_image (reg.rw),
505                       reg.name);
506     }
507 
508     for (i = 0; i < NUM_EXT_COND; i++)
509           if (arc_extension_map.condCodes[i])
510               printf ("COND: %s\n", arc_extension_map.condCodes[i]);
511 }
512 
513 /* For a given extension instruction generate the equivalent arc
514    opcode structure.  */
515 
516 struct arc_opcode *
arcExtMap_genOpcode(const extInstruction_t * einsn,unsigned arc_target,const char ** errmsg)517 arcExtMap_genOpcode (const extInstruction_t *einsn,
518                          unsigned arc_target,
519                          const char **errmsg)
520 {
521   struct arc_opcode *q, *arc_ext_opcodes = NULL;
522   const unsigned char *lflags_f;
523   const unsigned char *lflags_ccf;
524   int count;
525 
526   /* Check for the class to see how many instructions we generate.  */
527   switch (einsn->flags & ARC_SYNTAX_MASK)
528     {
529     case ARC_SYNTAX_3OP:
530       count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
531       break;
532     case ARC_SYNTAX_2OP:
533       count = (einsn->flags & 0x10) ? 7 : 6;
534       break;
535     case ARC_SYNTAX_1OP:
536       count = 3;
537       break;
538     case ARC_SYNTAX_NOP:
539       count = 1;
540       break;
541     default:
542       count = 0;
543       break;
544     }
545 
546   /* Allocate memory.  */
547   arc_ext_opcodes = (struct arc_opcode *)
548     xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
549 
550   if (arc_ext_opcodes == NULL)
551     {
552       *errmsg = "Virtual memory exhausted";
553       return NULL;
554     }
555 
556   /* Generate the patterns.  */
557   q = arc_ext_opcodes;
558 
559   if (einsn->suffix)
560     {
561       lflags_f   = flags_none;
562       lflags_ccf = flags_none;
563     }
564   else
565     {
566       lflags_f   = flags_f;
567       lflags_ccf = flags_ccf;
568     }
569 
570   if (einsn->suffix & ARC_SUFFIX_COND)
571     lflags_ccf = flags_cc;
572   if (einsn->suffix & ARC_SUFFIX_FLAG)
573     {
574       lflags_f   = flags_f;
575       lflags_ccf = flags_f;
576     }
577   if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
578     lflags_ccf = flags_ccf;
579 
580   if (einsn->flags & ARC_SYNTAX_2OP
581       && !(einsn->flags & 0x10))
582     {
583       /* Regular 2OP instruction.  */
584       if (einsn->suffix & ARC_SUFFIX_COND)
585           *errmsg = "Suffix SUFFIX_COND ignored";
586 
587       INSERT_XOP (q, einsn->name,
588                       INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
589                       arc_target, arg_32bit_rbrc, lflags_f);
590 
591       INSERT_XOP (q, einsn->name,
592                       INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
593                       arc_target, arg_32bit_zarc, lflags_f);
594 
595       INSERT_XOP (q, einsn->name,
596                       INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
597                       arc_target, arg_32bit_rbu6, lflags_f);
598 
599       INSERT_XOP (q, einsn->name,
600                       INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
601                       arc_target, arg_32bit_zau6, lflags_f);
602 
603       INSERT_XOP (q, einsn->name,
604                       INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
605                       arc_target, arg_32bit_rblimm, lflags_f);
606 
607       INSERT_XOP (q, einsn->name,
608                       INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
609                       arc_target, arg_32bit_zalimm, lflags_f);
610     }
611   else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
612     {
613       /* This is actually a 3OP pattern.  The first operand is
614            immplied and is set to zero.  */
615       INSERT_XOP (q, einsn->name,
616                       INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
617                       arc_target, arg_32bit_rbrc, lflags_f);
618 
619       INSERT_XOP (q, einsn->name,
620                       INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
621                       arc_target, arg_32bit_rbu6, lflags_f);
622 
623       INSERT_XOP (q, einsn->name,
624                       INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
625                       arc_target, arg_32bit_rblimm, lflags_f);
626 
627       INSERT_XOP (q, einsn->name,
628                       INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
629                       arc_target, arg_32bit_limmrc, lflags_ccf);
630 
631       INSERT_XOP (q, einsn->name,
632                       INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
633                       arc_target, arg_32bit_limmu6, lflags_ccf);
634 
635       INSERT_XOP (q, einsn->name,
636                       INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
637                       arc_target, arg_32bit_limms12, lflags_f);
638 
639       INSERT_XOP (q, einsn->name,
640                       INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
641                       arc_target, arg_32bit_limmlimm, lflags_ccf);
642     }
643   else if (einsn->flags & ARC_SYNTAX_3OP
644              && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
645     {
646       /* Regular 3OP instruction.  */
647       INSERT_XOP (q, einsn->name,
648                       INSN3OP_ABC (einsn->major, einsn->minor),  MINSN3OP_ABC,
649                       arc_target, arg_32bit_rarbrc, lflags_f);
650 
651       INSERT_XOP (q, einsn->name,
652                       INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
653                       arc_target, arg_32bit_zarbrc, lflags_f);
654 
655       INSERT_XOP (q, einsn->name,
656                       INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
657                       arc_target, arg_32bit_rbrbrc, lflags_ccf);
658 
659       INSERT_XOP (q, einsn->name,
660                       INSN3OP_ABU (einsn->major, einsn->minor),  MINSN3OP_ABU,
661                       arc_target, arg_32bit_rarbu6, lflags_f);
662 
663       INSERT_XOP (q, einsn->name,
664                       INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
665                       arc_target, arg_32bit_zarbu6, lflags_f);
666 
667       INSERT_XOP (q, einsn->name,
668                       INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
669                       arc_target, arg_32bit_rbrbu6, lflags_ccf);
670 
671       INSERT_XOP (q, einsn->name,
672                       INSN3OP_BBS (einsn->major, einsn->minor),  MINSN3OP_BBS,
673                       arc_target, arg_32bit_rbrbs12, lflags_f);
674 
675       INSERT_XOP (q, einsn->name,
676                       INSN3OP_ALC (einsn->major, einsn->minor),  MINSN3OP_ALC,
677                       arc_target, arg_32bit_ralimmrc, lflags_f);
678 
679       INSERT_XOP (q, einsn->name,
680                       INSN3OP_ABL (einsn->major, einsn->minor),  MINSN3OP_ABL,
681                       arc_target, arg_32bit_rarblimm, lflags_f);
682 
683       INSERT_XOP (q, einsn->name,
684                       INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
685                       arc_target, arg_32bit_zalimmrc, lflags_f);
686 
687       INSERT_XOP (q, einsn->name,
688                       INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
689                       arc_target, arg_32bit_zarblimm, lflags_f);
690 
691       INSERT_XOP (q, einsn->name,
692                       INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
693                       arc_target, arg_32bit_zalimmrc, lflags_ccf);
694 
695       INSERT_XOP (q, einsn->name,
696                       INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
697                       arc_target, arg_32bit_rbrblimm, lflags_ccf);
698 
699       INSERT_XOP (q, einsn->name,
700                       INSN3OP_ALU (einsn->major, einsn->minor),  MINSN3OP_ALU,
701                       arc_target, arg_32bit_ralimmu6, lflags_f);
702 
703       INSERT_XOP (q, einsn->name,
704                       INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
705                       arc_target, arg_32bit_zalimmu6, lflags_f);
706 
707       INSERT_XOP (q, einsn->name,
708                       INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
709                       arc_target, arg_32bit_zalimmu6, lflags_ccf);
710 
711       INSERT_XOP (q, einsn->name,
712                       INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
713                       arc_target, arg_32bit_zalimms12, lflags_f);
714 
715       INSERT_XOP (q, einsn->name,
716                       INSN3OP_ALL (einsn->major, einsn->minor),  MINSN3OP_ALL,
717                       arc_target, arg_32bit_ralimmlimm, lflags_f);
718 
719       INSERT_XOP (q, einsn->name,
720                       INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
721                       arc_target, arg_32bit_zalimmlimm, lflags_f);
722 
723       INSERT_XOP (q, einsn->name,
724                       INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
725                       arc_target, arg_32bit_zalimmlimm, lflags_ccf);
726     }
727   else if (einsn->flags & ARC_SYNTAX_3OP)
728     {
729       /* 3OP instruction which accepts only zero as first
730            argument.  */
731       INSERT_XOP (q, einsn->name,
732                       INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
733                       arc_target, arg_32bit_zarbrc, lflags_f);
734 
735       INSERT_XOP (q, einsn->name,
736                       INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
737                       arc_target, arg_32bit_zarbu6, lflags_f);
738 
739       INSERT_XOP (q, einsn->name,
740                       INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
741                       arc_target, arg_32bit_zalimmrc, lflags_f);
742 
743       INSERT_XOP (q, einsn->name,
744                       INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
745                       arc_target, arg_32bit_zarblimm, lflags_f);
746 
747       INSERT_XOP (q, einsn->name,
748                       INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
749                       arc_target, arg_32bit_zalimmrc, lflags_ccf);
750 
751       INSERT_XOP (q, einsn->name,
752                       INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
753                       arc_target, arg_32bit_zalimmu6, lflags_f);
754 
755       INSERT_XOP (q, einsn->name,
756                       INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
757                       arc_target, arg_32bit_zalimmu6, lflags_ccf);
758 
759       INSERT_XOP (q, einsn->name,
760                       INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
761                       arc_target, arg_32bit_zalimms12, lflags_f);
762 
763       INSERT_XOP (q, einsn->name,
764                       INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
765                       arc_target, arg_32bit_zalimmlimm, lflags_f);
766 
767       INSERT_XOP (q, einsn->name,
768                       INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
769                       arc_target, arg_32bit_zalimmlimm, lflags_ccf);
770     }
771   else if (einsn->flags & ARC_SYNTAX_1OP)
772     {
773       if (einsn->suffix & ARC_SUFFIX_COND)
774           *errmsg = "Suffix SUFFIX_COND ignored";
775 
776       INSERT_XOP (q, einsn->name,
777                       INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor),
778                       MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f);
779 
780       INSERT_XOP (q, einsn->name,
781                       INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
782                       | (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6,
783                       lflags_f);
784 
785       INSERT_XOP (q, einsn->name,
786                       INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
787                       | FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm,
788                       lflags_f);
789 
790     }
791   else if (einsn->flags & ARC_SYNTAX_NOP)
792     {
793       if (einsn->suffix & ARC_SUFFIX_COND)
794           *errmsg = "Suffix SUFFIX_COND ignored";
795 
796       INSERT_XOP (q, einsn->name,
797                       INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
798                       | (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f);
799     }
800   else
801     {
802       *errmsg = "Unknown syntax";
803       return NULL;
804     }
805 
806   /* End marker.  */
807   memset (q, 0, sizeof (*arc_ext_opcodes));
808 
809   return arc_ext_opcodes;
810 }
811