[BINUTILS, AARCH64, 6/8] Add Tag getting instruction in Memory Tagging Extension
[external/binutils.git] / opcodes / arc-ext.c
1 /* ARC target-dependent stuff.  Extension structure access functions
2    Copyright (C) 1995-2018 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   long                    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
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 = (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
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     {
249       if (arc_extension_map.coreRegisters[i].name)
250         free (arc_extension_map.coreRegisters[i].name);
251     }
252
253   /* Free condition codes.  */
254   for (i = 0; i < NUM_EXT_COND; i++)
255     {
256       if (arc_extension_map.condCodes[i])
257         free (arc_extension_map.condCodes[i]);
258     }
259
260   memset (&arc_extension_map, 0, sizeof (arc_extension_map));
261 }
262
263
264 static const char *
265 ExtReadWrite_image (enum ExtReadWrite val)
266 {
267     switch (val)
268     {
269         case REG_INVALID  : return "INVALID";
270         case REG_READ     : return "RO";
271         case REG_WRITE    : return "WO";
272         case REG_READWRITE: return "R/W";
273         default           : return "???";
274     }
275 }
276
277
278 /* Externally visible functions.  */
279
280 /* Get the name of an extension instruction.  */
281
282 const extInstruction_t *
283 arcExtMap_insn (int opcode, unsigned long long insn)
284 {
285   /* Here the following tasks need to be done.  First of all, the
286      opcode stored in the Extension Map is the real opcode.  However,
287      the subopcode stored in the instruction to be disassembled is
288      mangled.  We pass (in minor opcode), the instruction word.  Here
289      we will un-mangle it and get the real subopcode which we can look
290      for in the Extension Map.  This function is used both for the
291      ARCTangent and the ARCompact, so we would also need some sort of
292      a way to distinguish between the two architectures.  This is
293      because the ARCTangent does not do any of this mangling so we
294      have no issues there.  */
295
296   /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI.  If it is 1
297      then use iiiiIi.  Now, if P is 3 then check M[5:5] and if it is 0
298      then un-mangle using iiiiiI else iiiiii.  */
299
300   unsigned char minor;
301   extInstruction_t *temp;
302
303   /* 16-bit instructions.  */
304   if (0x08 <= opcode && opcode <= 0x0b)
305     {
306       unsigned char b, c, i;
307
308       b = (insn & 0x0700) >> 8;
309       c = (insn & 0x00e0) >> 5;
310       i = (insn & 0x001f);
311
312       if (i)
313         minor = i;
314       else
315         minor = (c == 0x07) ? b : c;
316     }
317   /* 32-bit instructions.  */
318   else
319     {
320       unsigned char I, A, B;
321
322       I = (insn & 0x003f0000) >> 16;
323       A = (insn & 0x0000003f);
324       B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
325
326       if (I != 0x2f)
327         {
328 #ifndef UNMANGLED
329           switch (P)
330             {
331             case 3:
332               if (M)
333                 {
334                   minor = I;
335                   break;
336                 }
337             case 0:
338             case 2:
339               minor = (I >> 1) | ((I & 0x1) << 5);
340               break;
341             case 1:
342               minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4);
343             }
344 #else
345           minor = I;
346 #endif
347         }
348       else
349         {
350           if (A != 0x3f)
351             minor = A;
352           else
353             minor = B;
354         }
355     }
356
357   temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
358   while (temp)
359     {
360       if ((temp->major == opcode) && (temp->minor == minor))
361         {
362           return temp;
363         }
364       temp = temp->next;
365     }
366
367   return NULL;
368 }
369
370 /* Get the name of an extension core register.  */
371
372 const char *
373 arcExtMap_coreRegName (int regnum)
374 {
375   if (regnum < FIRST_EXTENSION_CORE_REGISTER
376       || regnum > LAST_EXTENSION_CORE_REGISTER)
377     return NULL;
378   return arc_extension_map.
379     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name;
380 }
381
382 /* Get the access mode of an extension core register.  */
383
384 enum ExtReadWrite
385 arcExtMap_coreReadWrite (int regnum)
386 {
387   if (regnum < FIRST_EXTENSION_CORE_REGISTER
388       || regnum > LAST_EXTENSION_CORE_REGISTER)
389     return REG_INVALID;
390   return arc_extension_map.
391     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw;
392 }
393
394 /* Get the name of an extension condition code.  */
395
396 const char *
397 arcExtMap_condCodeName (int code)
398 {
399   if (code < FIRST_EXTENSION_CONDITION_CODE
400       || code > LAST_EXTENSION_CONDITION_CODE)
401     return NULL;
402   return arc_extension_map.
403     condCodes[code - FIRST_EXTENSION_CONDITION_CODE];
404 }
405
406 /* Get the name of an extension auxiliary register.  */
407
408 const char *
409 arcExtMap_auxRegName (long address)
410 {
411   /* Walk the list of auxiliary register names and find the name.  */
412   struct ExtAuxRegister *r;
413
414   for (r = arc_extension_map.auxRegisters; r; r = r->next)
415     {
416       if (r->address == address)
417         return (const char *)r->name;
418     }
419   return NULL;
420 }
421
422 /* Load extensions described in .arcextmap and
423    .gnu.linkonce.arcextmap.* ELF section.  */
424
425 void
426 build_ARC_extmap (bfd *text_bfd)
427 {
428   asection *sect;
429
430   /* The map is built each time gdb loads an executable file - so free
431      any existing map, as the map defined by the new file may differ
432      from the old.  */
433   destroy_map ();
434
435   for (sect = text_bfd->sections; sect != NULL; sect = sect->next)
436     if (!strncmp (sect->name,
437                   ".gnu.linkonce.arcextmap.",
438           sizeof (".gnu.linkonce.arcextmap.") - 1)
439         || !strcmp (sect->name,".arcextmap"))
440       {
441         bfd_size_type  count  = bfd_get_section_size (sect);
442         unsigned char* buffer = xmalloc (count);
443
444         if (buffer)
445           {
446             if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count))
447               create_map (buffer, count);
448             free (buffer);
449           }
450       }
451 }
452
453 /* Debug function used to dump the ARC information fount in arcextmap
454    sections.  */
455
456 void
457 dump_ARC_extmap (void)
458 {
459     struct ExtAuxRegister *r;
460     int                    i;
461
462     r = arc_extension_map.auxRegisters;
463
464     while (r)
465     {
466         printf ("AUX : %s %ld\n", r->name, r->address);
467         r = r->next;
468     }
469
470     for (i = 0; i < INST_HASH_SIZE; i++)
471     {
472         struct ExtInstruction *insn;
473
474         for (insn = arc_extension_map.instructions[i];
475              insn != NULL; insn = insn->next)
476           {
477             printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
478             switch (insn->flags & ARC_SYNTAX_MASK)
479               {
480               case ARC_SYNTAX_2OP:
481                 printf ("SYNTAX_2OP");
482                 break;
483               case ARC_SYNTAX_3OP:
484                 printf ("SYNTAX_3OP");
485                 break;
486               case ARC_SYNTAX_1OP:
487                 printf ("SYNTAX_1OP");
488                 break;
489               case ARC_SYNTAX_NOP:
490                 printf ("SYNTAX_NOP");
491                 break;
492               default:
493                 printf ("SYNTAX_UNK");
494                 break;
495               }
496
497             if (insn->flags & 0x10)
498               printf ("|MODIFIER");
499
500             printf (" %s\n", insn->name);
501           }
502     }
503
504     for (i = 0; i < NUM_EXT_CORE; i++)
505     {
506         struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
507
508         if (reg.name)
509           printf ("CORE: 0x%04x %s %s\n", reg.number,
510                   ExtReadWrite_image (reg.rw),
511                   reg.name);
512     }
513
514     for (i = 0; i < NUM_EXT_COND; i++)
515         if (arc_extension_map.condCodes[i])
516             printf ("COND: %s\n", arc_extension_map.condCodes[i]);
517 }
518
519 /* For a given extension instruction generate the equivalent arc
520    opcode structure.  */
521
522 struct arc_opcode *
523 arcExtMap_genOpcode (const extInstruction_t *einsn,
524                      unsigned arc_target,
525                      const char **errmsg)
526 {
527   struct arc_opcode *q, *arc_ext_opcodes = NULL;
528   const unsigned char *lflags_f;
529   const unsigned char *lflags_ccf;
530   int count;
531
532   /* Check for the class to see how many instructions we generate.  */
533   switch (einsn->flags & ARC_SYNTAX_MASK)
534     {
535     case ARC_SYNTAX_3OP:
536       count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
537       break;
538     case ARC_SYNTAX_2OP:
539       count = (einsn->flags & 0x10) ? 7 : 6;
540       break;
541     case ARC_SYNTAX_1OP:
542       count = 3;
543       break;
544     case ARC_SYNTAX_NOP:
545       count = 1;
546       break;
547     default:
548       count = 0;
549       break;
550     }
551
552   /* Allocate memory.  */
553   arc_ext_opcodes = (struct arc_opcode *)
554     xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
555
556   if (arc_ext_opcodes == NULL)
557     {
558       *errmsg = "Virtual memory exhausted";
559       return NULL;
560     }
561
562   /* Generate the patterns.  */
563   q = arc_ext_opcodes;
564
565   if (einsn->suffix)
566     {
567       lflags_f   = flags_none;
568       lflags_ccf = flags_none;
569     }
570   else
571     {
572       lflags_f   = flags_f;
573       lflags_ccf = flags_ccf;
574     }
575
576   if (einsn->suffix & ARC_SUFFIX_COND)
577     lflags_ccf = flags_cc;
578   if (einsn->suffix & ARC_SUFFIX_FLAG)
579     {
580       lflags_f   = flags_f;
581       lflags_ccf = flags_f;
582     }
583   if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
584     lflags_ccf = flags_ccf;
585
586   if (einsn->flags & ARC_SYNTAX_2OP
587       && !(einsn->flags & 0x10))
588     {
589       /* Regular 2OP instruction.  */
590       if (einsn->suffix & ARC_SUFFIX_COND)
591         *errmsg = "Suffix SUFFIX_COND ignored";
592
593       INSERT_XOP (q, einsn->name,
594                   INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
595                   arc_target, arg_32bit_rbrc, lflags_f);
596
597       INSERT_XOP (q, einsn->name,
598                   INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
599                   arc_target, arg_32bit_zarc, lflags_f);
600
601       INSERT_XOP (q, einsn->name,
602                   INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
603                   arc_target, arg_32bit_rbu6, lflags_f);
604
605       INSERT_XOP (q, einsn->name,
606                   INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
607                   arc_target, arg_32bit_zau6, lflags_f);
608
609       INSERT_XOP (q, einsn->name,
610                   INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
611                   arc_target, arg_32bit_rblimm, lflags_f);
612
613       INSERT_XOP (q, einsn->name,
614                   INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
615                   arc_target, arg_32bit_zalimm, lflags_f);
616     }
617   else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
618     {
619       /* This is actually a 3OP pattern.  The first operand is
620          immplied and is set to zero.  */
621       INSERT_XOP (q, einsn->name,
622                   INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
623                   arc_target, arg_32bit_rbrc, lflags_f);
624
625       INSERT_XOP (q, einsn->name,
626                   INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
627                   arc_target, arg_32bit_rbu6, lflags_f);
628
629       INSERT_XOP (q, einsn->name,
630                   INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
631                   arc_target, arg_32bit_rblimm, lflags_f);
632
633       INSERT_XOP (q, einsn->name,
634                   INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
635                   arc_target, arg_32bit_limmrc, lflags_ccf);
636
637       INSERT_XOP (q, einsn->name,
638                   INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
639                   arc_target, arg_32bit_limmu6, lflags_ccf);
640
641       INSERT_XOP (q, einsn->name,
642                   INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
643                   arc_target, arg_32bit_limms12, lflags_f);
644
645       INSERT_XOP (q, einsn->name,
646                   INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
647                   arc_target, arg_32bit_limmlimm, lflags_ccf);
648     }
649   else if (einsn->flags & ARC_SYNTAX_3OP
650            && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
651     {
652       /* Regular 3OP instruction.  */
653       INSERT_XOP (q, einsn->name,
654                   INSN3OP_ABC (einsn->major, einsn->minor),  MINSN3OP_ABC,
655                   arc_target, arg_32bit_rarbrc, lflags_f);
656
657       INSERT_XOP (q, einsn->name,
658                   INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
659                   arc_target, arg_32bit_zarbrc, lflags_f);
660
661       INSERT_XOP (q, einsn->name,
662                   INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
663                   arc_target, arg_32bit_rbrbrc, lflags_ccf);
664
665       INSERT_XOP (q, einsn->name,
666                   INSN3OP_ABU (einsn->major, einsn->minor),  MINSN3OP_ABU,
667                   arc_target, arg_32bit_rarbu6, lflags_f);
668
669       INSERT_XOP (q, einsn->name,
670                   INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
671                   arc_target, arg_32bit_zarbu6, lflags_f);
672
673       INSERT_XOP (q, einsn->name,
674                   INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
675                   arc_target, arg_32bit_rbrbu6, lflags_ccf);
676
677       INSERT_XOP (q, einsn->name,
678                   INSN3OP_BBS (einsn->major, einsn->minor),  MINSN3OP_BBS,
679                   arc_target, arg_32bit_rbrbs12, lflags_f);
680
681       INSERT_XOP (q, einsn->name,
682                   INSN3OP_ALC (einsn->major, einsn->minor),  MINSN3OP_ALC,
683                   arc_target, arg_32bit_ralimmrc, lflags_f);
684
685       INSERT_XOP (q, einsn->name,
686                   INSN3OP_ABL (einsn->major, einsn->minor),  MINSN3OP_ABL,
687                   arc_target, arg_32bit_rarblimm, lflags_f);
688
689       INSERT_XOP (q, einsn->name,
690                   INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
691                   arc_target, arg_32bit_zalimmrc, lflags_f);
692
693       INSERT_XOP (q, einsn->name,
694                   INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
695                   arc_target, arg_32bit_zarblimm, lflags_f);
696
697       INSERT_XOP (q, einsn->name,
698                   INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
699                   arc_target, arg_32bit_zalimmrc, lflags_ccf);
700
701       INSERT_XOP (q, einsn->name,
702                   INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
703                   arc_target, arg_32bit_rbrblimm, lflags_ccf);
704
705       INSERT_XOP (q, einsn->name,
706                   INSN3OP_ALU (einsn->major, einsn->minor),  MINSN3OP_ALU,
707                   arc_target, arg_32bit_ralimmu6, lflags_f);
708
709       INSERT_XOP (q, einsn->name,
710                   INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
711                   arc_target, arg_32bit_zalimmu6, lflags_f);
712
713       INSERT_XOP (q, einsn->name,
714                   INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
715                   arc_target, arg_32bit_zalimmu6, lflags_ccf);
716
717       INSERT_XOP (q, einsn->name,
718                   INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
719                   arc_target, arg_32bit_zalimms12, lflags_f);
720
721       INSERT_XOP (q, einsn->name,
722                   INSN3OP_ALL (einsn->major, einsn->minor),  MINSN3OP_ALL,
723                   arc_target, arg_32bit_ralimmlimm, lflags_f);
724
725       INSERT_XOP (q, einsn->name,
726                   INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
727                   arc_target, arg_32bit_zalimmlimm, lflags_f);
728
729       INSERT_XOP (q, einsn->name,
730                   INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
731                   arc_target, arg_32bit_zalimmlimm, lflags_ccf);
732     }
733   else if (einsn->flags & ARC_SYNTAX_3OP)
734     {
735       /* 3OP instruction which accepts only zero as first
736          argument.  */
737       INSERT_XOP (q, einsn->name,
738                   INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
739                   arc_target, arg_32bit_zarbrc, lflags_f);
740
741       INSERT_XOP (q, einsn->name,
742                   INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
743                   arc_target, arg_32bit_zarbu6, lflags_f);
744
745       INSERT_XOP (q, einsn->name,
746                   INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
747                   arc_target, arg_32bit_zalimmrc, lflags_f);
748
749       INSERT_XOP (q, einsn->name,
750                   INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
751                   arc_target, arg_32bit_zarblimm, lflags_f);
752
753       INSERT_XOP (q, einsn->name,
754                   INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
755                   arc_target, arg_32bit_zalimmrc, lflags_ccf);
756
757       INSERT_XOP (q, einsn->name,
758                   INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
759                   arc_target, arg_32bit_zalimmu6, lflags_f);
760
761       INSERT_XOP (q, einsn->name,
762                   INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
763                   arc_target, arg_32bit_zalimmu6, lflags_ccf);
764
765       INSERT_XOP (q, einsn->name,
766                   INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
767                   arc_target, arg_32bit_zalimms12, lflags_f);
768
769       INSERT_XOP (q, einsn->name,
770                   INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
771                   arc_target, arg_32bit_zalimmlimm, lflags_f);
772
773       INSERT_XOP (q, einsn->name,
774                   INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
775                   arc_target, arg_32bit_zalimmlimm, lflags_ccf);
776     }
777   else if (einsn->flags & ARC_SYNTAX_1OP)
778     {
779       if (einsn->suffix & ARC_SUFFIX_COND)
780         *errmsg = "Suffix SUFFIX_COND ignored";
781
782       INSERT_XOP (q, einsn->name,
783                   INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor),
784                   MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f);
785
786       INSERT_XOP (q, einsn->name,
787                   INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
788                   | (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6,
789                   lflags_f);
790
791       INSERT_XOP (q, einsn->name,
792                   INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
793                   | FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm,
794                   lflags_f);
795
796     }
797   else if (einsn->flags & ARC_SYNTAX_NOP)
798     {
799       if (einsn->suffix & ARC_SUFFIX_COND)
800         *errmsg = "Suffix SUFFIX_COND ignored";
801
802       INSERT_XOP (q, einsn->name,
803                   INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
804                   | (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f);
805     }
806   else
807     {
808       *errmsg = "Unknown syntax";
809       return NULL;
810     }
811
812   /* End marker.  */
813   memset (q, 0, sizeof (*arc_ext_opcodes));
814
815   return arc_ext_opcodes;
816 }