1/* ARC target-dependent stuff.  Extension structure access functions
2   Copyright (C) 1995-2017 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
54struct ExtAuxRegister
55{
56  long			  address;
57  char *		  name;
58  struct ExtAuxRegister * next;
59};
60
61struct ExtCoreRegister
62{
63  short		    number;
64  enum ExtReadWrite rw;
65  char *	    name;
66};
67
68struct 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.  */
80static 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
91static void
92create_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
212static void
213destroy_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
264static const char *
265ExtReadWrite_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
282const extInstruction_t *
283arcExtMap_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
372const char *
373arcExtMap_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
384enum ExtReadWrite
385arcExtMap_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
396const char *
397arcExtMap_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
408const char *
409arcExtMap_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
425void
426build_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
456void
457dump_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
522struct arc_opcode *
523arcExtMap_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