xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/arc-ext.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
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 }
817