12a6b7db3Sskrll /* ARC target-dependent stuff. Extension structure access functions
2*cb63e24eSchristos Copyright (C) 1995-2024 Free Software Foundation, Inc.
32a6b7db3Sskrll
42a6b7db3Sskrll This file is part of libopcodes.
52a6b7db3Sskrll
62a6b7db3Sskrll This library is free software; you can redistribute it and/or modify
72a6b7db3Sskrll it under the terms of the GNU General Public License as published by
82a6b7db3Sskrll the Free Software Foundation; either version 3, or (at your option)
92a6b7db3Sskrll any later version.
102a6b7db3Sskrll
112a6b7db3Sskrll It is distributed in the hope that it will be useful, but WITHOUT
122a6b7db3Sskrll ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
132a6b7db3Sskrll or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
142a6b7db3Sskrll License for more details.
152a6b7db3Sskrll
162a6b7db3Sskrll You should have received a copy of the GNU General Public License
172a6b7db3Sskrll along with this program; if not, write to the Free Software
182a6b7db3Sskrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
192a6b7db3Sskrll MA 02110-1301, USA. */
202a6b7db3Sskrll
212a6b7db3Sskrll #include "sysdep.h"
222a6b7db3Sskrll #include <stdlib.h>
232a6b7db3Sskrll #include <stdio.h>
249573673dSchristos
252a6b7db3Sskrll #include "bfd.h"
262a6b7db3Sskrll #include "arc-ext.h"
279573673dSchristos #include "elf/arc.h"
282a6b7db3Sskrll #include "libiberty.h"
292a6b7db3Sskrll
309573673dSchristos /* This module provides support for extensions to the ARC processor
319573673dSchristos architecture. */
329573673dSchristos
339573673dSchristos
349573673dSchristos /* Local constants. */
359573673dSchristos
369573673dSchristos #define FIRST_EXTENSION_CORE_REGISTER 32
379573673dSchristos #define LAST_EXTENSION_CORE_REGISTER 59
389573673dSchristos #define FIRST_EXTENSION_CONDITION_CODE 0x10
399573673dSchristos #define LAST_EXTENSION_CONDITION_CODE 0x1f
409573673dSchristos
419573673dSchristos #define NUM_EXT_CORE \
429573673dSchristos (LAST_EXTENSION_CORE_REGISTER - FIRST_EXTENSION_CORE_REGISTER + 1)
439573673dSchristos #define NUM_EXT_COND \
449573673dSchristos (LAST_EXTENSION_CONDITION_CODE - FIRST_EXTENSION_CONDITION_CODE + 1)
459573673dSchristos #define INST_HASH_BITS 6
469573673dSchristos #define INST_HASH_SIZE (1 << INST_HASH_BITS)
479573673dSchristos #define INST_HASH_MASK (INST_HASH_SIZE - 1)
489573673dSchristos
499573673dSchristos
509573673dSchristos /* Local types. */
519573673dSchristos
529573673dSchristos /* These types define the information stored in the table. */
539573673dSchristos
549573673dSchristos struct ExtAuxRegister
559573673dSchristos {
566f4ced0bSchristos unsigned address;
579573673dSchristos char * name;
589573673dSchristos struct ExtAuxRegister * next;
599573673dSchristos };
609573673dSchristos
619573673dSchristos struct ExtCoreRegister
629573673dSchristos {
639573673dSchristos short number;
649573673dSchristos enum ExtReadWrite rw;
659573673dSchristos char * name;
669573673dSchristos };
679573673dSchristos
689573673dSchristos struct arcExtMap
699573673dSchristos {
709573673dSchristos struct ExtAuxRegister* auxRegisters;
719573673dSchristos struct ExtInstruction* instructions[INST_HASH_SIZE];
729573673dSchristos struct ExtCoreRegister coreRegisters[NUM_EXT_CORE];
739573673dSchristos char * condCodes[NUM_EXT_COND];
749573673dSchristos };
759573673dSchristos
769573673dSchristos
779573673dSchristos /* Local data. */
789573673dSchristos
799573673dSchristos /* Extension table. */
802a6b7db3Sskrll static struct arcExtMap arc_extension_map;
812a6b7db3Sskrll
822a6b7db3Sskrll
839573673dSchristos /* Local macros. */
842a6b7db3Sskrll
859573673dSchristos /* A hash function used to map instructions into the table. */
869573673dSchristos #define INST_HASH(MAJOR, MINOR) ((((MAJOR) << 3) ^ (MINOR)) & INST_HASH_MASK)
872a6b7db3Sskrll
882a6b7db3Sskrll
899573673dSchristos /* Local functions. */
902a6b7db3Sskrll
912a6b7db3Sskrll static void
create_map(unsigned char * block,unsigned long length)929573673dSchristos create_map (unsigned char *block,
939573673dSchristos unsigned long length)
942a6b7db3Sskrll {
959573673dSchristos unsigned char *p = block;
962a6b7db3Sskrll
972a6b7db3Sskrll while (p && p < (block + length))
982a6b7db3Sskrll {
992a6b7db3Sskrll /* p[0] == length of record
1002a6b7db3Sskrll p[1] == type of record
1012a6b7db3Sskrll For instructions:
1022a6b7db3Sskrll p[2] = opcode
1032a6b7db3Sskrll p[3] = minor opcode (if opcode == 3)
1042a6b7db3Sskrll p[4] = flags
1052a6b7db3Sskrll p[5]+ = name
1062a6b7db3Sskrll For core regs and condition codes:
1072a6b7db3Sskrll p[2] = value
1082a6b7db3Sskrll p[3]+ = name
1099573673dSchristos For auxiliary regs:
1102a6b7db3Sskrll p[2..5] = value
1112a6b7db3Sskrll p[6]+ = name
1129573673dSchristos (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]). */
1132a6b7db3Sskrll
1149573673dSchristos /* The sequence of records is temrinated by an "empty"
1159573673dSchristos record. */
1162a6b7db3Sskrll if (p[0] == 0)
1179573673dSchristos break;
1182a6b7db3Sskrll
1192a6b7db3Sskrll switch (p[1])
1202a6b7db3Sskrll {
1212a6b7db3Sskrll case EXT_INSTRUCTION:
1222a6b7db3Sskrll {
1239573673dSchristos struct ExtInstruction *insn = XNEW (struct ExtInstruction);
1249573673dSchristos int major = p[2];
1259573673dSchristos int minor = p[3];
1269573673dSchristos struct ExtInstruction **bucket =
1279573673dSchristos &arc_extension_map.instructions[INST_HASH (major, minor)];
1282a6b7db3Sskrll
1299573673dSchristos insn->name = xstrdup ((char *) (p + 5));
1309573673dSchristos insn->major = major;
1319573673dSchristos insn->minor = minor;
1329573673dSchristos insn->flags = p[4];
1339573673dSchristos insn->next = *bucket;
1348cbf5cb7Schristos insn->suffix = 0;
1358cbf5cb7Schristos insn->syntax = 0;
1368cbf5cb7Schristos insn->modsyn = 0;
1379573673dSchristos *bucket = insn;
1382a6b7db3Sskrll break;
1399573673dSchristos }
1402a6b7db3Sskrll
1412a6b7db3Sskrll case EXT_CORE_REGISTER:
1422a6b7db3Sskrll {
1439573673dSchristos unsigned char number = p[2];
1449573673dSchristos char* name = (char *) (p + 3);
1452a6b7db3Sskrll
1469573673dSchristos arc_extension_map.
1479573673dSchristos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
1489573673dSchristos = number;
1499573673dSchristos arc_extension_map.
1509573673dSchristos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
1519573673dSchristos = REG_READWRITE;
1529573673dSchristos arc_extension_map.
1539573673dSchristos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
1549573673dSchristos = xstrdup (name);
1552a6b7db3Sskrll break;
1569573673dSchristos }
1579573673dSchristos
1589573673dSchristos case EXT_LONG_CORE_REGISTER:
1599573673dSchristos {
1609573673dSchristos unsigned char number = p[2];
1619573673dSchristos char* name = (char *) (p + 7);
1629573673dSchristos enum ExtReadWrite rw = p[6];
1639573673dSchristos
1649573673dSchristos arc_extension_map.
1659573673dSchristos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
1669573673dSchristos = number;
1679573673dSchristos arc_extension_map.
1689573673dSchristos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
1699573673dSchristos = rw;
1709573673dSchristos arc_extension_map.
1719573673dSchristos coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
1729573673dSchristos = xstrdup (name);
173fc4f4269Schristos break;
1749573673dSchristos }
1752a6b7db3Sskrll
1762a6b7db3Sskrll case EXT_COND_CODE:
1772a6b7db3Sskrll {
1789573673dSchristos char *cc_name = xstrdup ((char *) (p + 3));
1799573673dSchristos
1809573673dSchristos arc_extension_map.
1819573673dSchristos condCodes[p[2] - FIRST_EXTENSION_CONDITION_CODE]
1829573673dSchristos = cc_name;
1832a6b7db3Sskrll break;
1849573673dSchristos }
1852a6b7db3Sskrll
1862a6b7db3Sskrll case EXT_AUX_REGISTER:
1872a6b7db3Sskrll {
1889573673dSchristos /* Trickier -- need to store linked list of these. */
1899573673dSchristos struct ExtAuxRegister *newAuxRegister
1909573673dSchristos = XNEW (struct ExtAuxRegister);
1919573673dSchristos char *aux_name = xstrdup ((char *) (p + 6));
1922a6b7db3Sskrll
1932a6b7db3Sskrll newAuxRegister->name = aux_name;
1946f4ced0bSchristos newAuxRegister->address = (((unsigned) p[2] << 24) | (p[3] << 16)
1956f4ced0bSchristos | (p[4] << 8) | p[5]);
1962a6b7db3Sskrll newAuxRegister->next = arc_extension_map.auxRegisters;
1972a6b7db3Sskrll arc_extension_map.auxRegisters = newAuxRegister;
1982a6b7db3Sskrll break;
1999573673dSchristos }
2002a6b7db3Sskrll
2012a6b7db3Sskrll default:
2022a6b7db3Sskrll break;
2032a6b7db3Sskrll }
2049573673dSchristos
2059573673dSchristos p += p[0]; /* Move on to next record. */
2062a6b7db3Sskrll }
2072a6b7db3Sskrll }
2089573673dSchristos
2099573673dSchristos
2109573673dSchristos /* Free memory that has been allocated for the extensions. */
2119573673dSchristos
2129573673dSchristos static void
destroy_map(void)2139573673dSchristos destroy_map (void)
2149573673dSchristos {
2159573673dSchristos struct ExtAuxRegister *r;
2169573673dSchristos unsigned int i;
2179573673dSchristos
2189573673dSchristos /* Free auxiliary registers. */
2199573673dSchristos r = arc_extension_map.auxRegisters;
2209573673dSchristos while (r)
2219573673dSchristos {
2229573673dSchristos /* N.B. after r has been freed, r->next is invalid! */
2239573673dSchristos struct ExtAuxRegister* next = r->next;
2249573673dSchristos
2259573673dSchristos free (r->name);
2269573673dSchristos free (r);
2279573673dSchristos r = next;
2289573673dSchristos }
2299573673dSchristos
2309573673dSchristos /* Free instructions. */
2319573673dSchristos for (i = 0; i < INST_HASH_SIZE; i++)
2329573673dSchristos {
2339573673dSchristos struct ExtInstruction *insn = arc_extension_map.instructions[i];
2349573673dSchristos
2359573673dSchristos while (insn)
2369573673dSchristos {
2379573673dSchristos /* N.B. after insn has been freed, insn->next is invalid! */
2389573673dSchristos struct ExtInstruction *next = insn->next;
2399573673dSchristos
2409573673dSchristos free (insn->name);
2419573673dSchristos free (insn);
2429573673dSchristos insn = next;
2439573673dSchristos }
2449573673dSchristos }
2459573673dSchristos
2469573673dSchristos /* Free core registers. */
2479573673dSchristos for (i = 0; i < NUM_EXT_CORE; i++)
2489573673dSchristos free (arc_extension_map.coreRegisters[i].name);
2499573673dSchristos
2509573673dSchristos /* Free condition codes. */
2519573673dSchristos for (i = 0; i < NUM_EXT_COND; i++)
2529573673dSchristos free (arc_extension_map.condCodes[i]);
2539573673dSchristos
2549573673dSchristos memset (&arc_extension_map, 0, sizeof (arc_extension_map));
2559573673dSchristos }
2569573673dSchristos
2579573673dSchristos
2589573673dSchristos static const char *
ExtReadWrite_image(enum ExtReadWrite val)2599573673dSchristos ExtReadWrite_image (enum ExtReadWrite val)
2609573673dSchristos {
2619573673dSchristos switch (val)
2629573673dSchristos {
2639573673dSchristos case REG_INVALID : return "INVALID";
2649573673dSchristos case REG_READ : return "RO";
2659573673dSchristos case REG_WRITE : return "WO";
2669573673dSchristos case REG_READWRITE: return "R/W";
2679573673dSchristos default : return "???";
2689573673dSchristos }
2699573673dSchristos }
2709573673dSchristos
2719573673dSchristos
2729573673dSchristos /* Externally visible functions. */
2739573673dSchristos
2749573673dSchristos /* Get the name of an extension instruction. */
2759573673dSchristos
2768cbf5cb7Schristos const extInstruction_t *
arcExtMap_insn(int opcode,unsigned long long insn)277fc4f4269Schristos arcExtMap_insn (int opcode, unsigned long long insn)
2789573673dSchristos {
2799573673dSchristos /* Here the following tasks need to be done. First of all, the
2809573673dSchristos opcode stored in the Extension Map is the real opcode. However,
2819573673dSchristos the subopcode stored in the instruction to be disassembled is
2829573673dSchristos mangled. We pass (in minor opcode), the instruction word. Here
2839573673dSchristos we will un-mangle it and get the real subopcode which we can look
2849573673dSchristos for in the Extension Map. This function is used both for the
2859573673dSchristos ARCTangent and the ARCompact, so we would also need some sort of
2869573673dSchristos a way to distinguish between the two architectures. This is
2879573673dSchristos because the ARCTangent does not do any of this mangling so we
2889573673dSchristos have no issues there. */
2899573673dSchristos
2909573673dSchristos /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI. If it is 1
2919573673dSchristos then use iiiiIi. Now, if P is 3 then check M[5:5] and if it is 0
2929573673dSchristos then un-mangle using iiiiiI else iiiiii. */
2939573673dSchristos
2949573673dSchristos unsigned char minor;
2958cbf5cb7Schristos extInstruction_t *temp;
2969573673dSchristos
2979573673dSchristos /* 16-bit instructions. */
2989573673dSchristos if (0x08 <= opcode && opcode <= 0x0b)
2999573673dSchristos {
3009573673dSchristos unsigned char b, c, i;
3019573673dSchristos
3029573673dSchristos b = (insn & 0x0700) >> 8;
3039573673dSchristos c = (insn & 0x00e0) >> 5;
3049573673dSchristos i = (insn & 0x001f);
3059573673dSchristos
3069573673dSchristos if (i)
3079573673dSchristos minor = i;
3089573673dSchristos else
3099573673dSchristos minor = (c == 0x07) ? b : c;
3109573673dSchristos }
3119573673dSchristos /* 32-bit instructions. */
3129573673dSchristos else
3139573673dSchristos {
3149573673dSchristos unsigned char I, A, B;
3159573673dSchristos
3169573673dSchristos I = (insn & 0x003f0000) >> 16;
3179573673dSchristos A = (insn & 0x0000003f);
3189573673dSchristos B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
3199573673dSchristos
3209573673dSchristos if (I != 0x2f)
3219573673dSchristos {
3229573673dSchristos #ifndef UNMANGLED
3239573673dSchristos switch (P)
3249573673dSchristos {
3259573673dSchristos case 3:
3269573673dSchristos if (M)
3279573673dSchristos {
3289573673dSchristos minor = I;
3299573673dSchristos break;
3309573673dSchristos }
3319573673dSchristos case 0:
3329573673dSchristos case 2:
3339573673dSchristos minor = (I >> 1) | ((I & 0x1) << 5);
3349573673dSchristos break;
3359573673dSchristos case 1:
3369573673dSchristos minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4);
3379573673dSchristos }
3389573673dSchristos #else
3399573673dSchristos minor = I;
3409573673dSchristos #endif
3419573673dSchristos }
3429573673dSchristos else
3439573673dSchristos {
3449573673dSchristos if (A != 0x3f)
3459573673dSchristos minor = A;
3469573673dSchristos else
3479573673dSchristos minor = B;
3489573673dSchristos }
3499573673dSchristos }
3509573673dSchristos
3519573673dSchristos temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
3529573673dSchristos while (temp)
3539573673dSchristos {
3549573673dSchristos if ((temp->major == opcode) && (temp->minor == minor))
3559573673dSchristos {
3568cbf5cb7Schristos return temp;
3579573673dSchristos }
3589573673dSchristos temp = temp->next;
3599573673dSchristos }
3609573673dSchristos
3619573673dSchristos return NULL;
3629573673dSchristos }
3639573673dSchristos
3649573673dSchristos /* Get the name of an extension core register. */
3659573673dSchristos
3669573673dSchristos const char *
arcExtMap_coreRegName(int regnum)3679573673dSchristos arcExtMap_coreRegName (int regnum)
3689573673dSchristos {
3699573673dSchristos if (regnum < FIRST_EXTENSION_CORE_REGISTER
3708cbf5cb7Schristos || regnum > LAST_EXTENSION_CORE_REGISTER)
3719573673dSchristos return NULL;
3729573673dSchristos return arc_extension_map.
3739573673dSchristos coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name;
3749573673dSchristos }
3759573673dSchristos
3769573673dSchristos /* Get the access mode of an extension core register. */
3779573673dSchristos
3789573673dSchristos enum ExtReadWrite
arcExtMap_coreReadWrite(int regnum)3799573673dSchristos arcExtMap_coreReadWrite (int regnum)
3809573673dSchristos {
3819573673dSchristos if (regnum < FIRST_EXTENSION_CORE_REGISTER
3828cbf5cb7Schristos || regnum > LAST_EXTENSION_CORE_REGISTER)
3839573673dSchristos return REG_INVALID;
3849573673dSchristos return arc_extension_map.
3859573673dSchristos coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw;
3869573673dSchristos }
3879573673dSchristos
3889573673dSchristos /* Get the name of an extension condition code. */
3899573673dSchristos
3909573673dSchristos const char *
arcExtMap_condCodeName(int code)3919573673dSchristos arcExtMap_condCodeName (int code)
3929573673dSchristos {
3939573673dSchristos if (code < FIRST_EXTENSION_CONDITION_CODE
3949573673dSchristos || code > LAST_EXTENSION_CONDITION_CODE)
3959573673dSchristos return NULL;
3969573673dSchristos return arc_extension_map.
3979573673dSchristos condCodes[code - FIRST_EXTENSION_CONDITION_CODE];
3989573673dSchristos }
3999573673dSchristos
4009573673dSchristos /* Get the name of an extension auxiliary register. */
4019573673dSchristos
4029573673dSchristos const char *
arcExtMap_auxRegName(unsigned address)4036f4ced0bSchristos arcExtMap_auxRegName (unsigned address)
4049573673dSchristos {
4059573673dSchristos /* Walk the list of auxiliary register names and find the name. */
4069573673dSchristos struct ExtAuxRegister *r;
4079573673dSchristos
4089573673dSchristos for (r = arc_extension_map.auxRegisters; r; r = r->next)
4099573673dSchristos {
4109573673dSchristos if (r->address == address)
4119573673dSchristos return (const char *)r->name;
4129573673dSchristos }
4139573673dSchristos return NULL;
4149573673dSchristos }
4159573673dSchristos
4169573673dSchristos /* Load extensions described in .arcextmap and
4179573673dSchristos .gnu.linkonce.arcextmap.* ELF section. */
4189573673dSchristos
4199573673dSchristos void
build_ARC_extmap(bfd * text_bfd)4209573673dSchristos build_ARC_extmap (bfd *text_bfd)
4219573673dSchristos {
4229573673dSchristos asection *sect;
4239573673dSchristos
4249573673dSchristos /* The map is built each time gdb loads an executable file - so free
4259573673dSchristos any existing map, as the map defined by the new file may differ
4269573673dSchristos from the old. */
4279573673dSchristos destroy_map ();
4289573673dSchristos
4299573673dSchristos for (sect = text_bfd->sections; sect != NULL; sect = sect->next)
4309573673dSchristos if (!strncmp (sect->name,
4319573673dSchristos ".gnu.linkonce.arcextmap.",
4329573673dSchristos sizeof (".gnu.linkonce.arcextmap.") - 1)
4339573673dSchristos || !strcmp (sect->name,".arcextmap"))
4349573673dSchristos {
4356f4ced0bSchristos bfd_size_type count = bfd_section_size (sect);
4369573673dSchristos unsigned char* buffer = xmalloc (count);
4379573673dSchristos
4389573673dSchristos if (buffer)
4399573673dSchristos {
4409573673dSchristos if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count))
4419573673dSchristos create_map (buffer, count);
4429573673dSchristos free (buffer);
4439573673dSchristos }
4449573673dSchristos }
4459573673dSchristos }
4469573673dSchristos
4478cbf5cb7Schristos /* Debug function used to dump the ARC information fount in arcextmap
4488cbf5cb7Schristos sections. */
4499573673dSchristos
4509573673dSchristos void
dump_ARC_extmap(void)4519573673dSchristos dump_ARC_extmap (void)
4529573673dSchristos {
4539573673dSchristos struct ExtAuxRegister *r;
4549573673dSchristos int i;
4559573673dSchristos
4569573673dSchristos r = arc_extension_map.auxRegisters;
4579573673dSchristos
4589573673dSchristos while (r)
4599573673dSchristos {
4606f4ced0bSchristos printf ("AUX : %s %u\n", r->name, r->address);
4619573673dSchristos r = r->next;
4629573673dSchristos }
4639573673dSchristos
4649573673dSchristos for (i = 0; i < INST_HASH_SIZE; i++)
4659573673dSchristos {
4669573673dSchristos struct ExtInstruction *insn;
4679573673dSchristos
4689573673dSchristos for (insn = arc_extension_map.instructions[i];
4699573673dSchristos insn != NULL; insn = insn->next)
4708cbf5cb7Schristos {
4718cbf5cb7Schristos printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
4728cbf5cb7Schristos switch (insn->flags & ARC_SYNTAX_MASK)
4738cbf5cb7Schristos {
4748cbf5cb7Schristos case ARC_SYNTAX_2OP:
4758cbf5cb7Schristos printf ("SYNTAX_2OP");
4768cbf5cb7Schristos break;
4778cbf5cb7Schristos case ARC_SYNTAX_3OP:
4788cbf5cb7Schristos printf ("SYNTAX_3OP");
4798cbf5cb7Schristos break;
4808cbf5cb7Schristos case ARC_SYNTAX_1OP:
4818cbf5cb7Schristos printf ("SYNTAX_1OP");
4828cbf5cb7Schristos break;
4838cbf5cb7Schristos case ARC_SYNTAX_NOP:
4848cbf5cb7Schristos printf ("SYNTAX_NOP");
4858cbf5cb7Schristos break;
4868cbf5cb7Schristos default:
4878cbf5cb7Schristos printf ("SYNTAX_UNK");
4888cbf5cb7Schristos break;
4898cbf5cb7Schristos }
4908cbf5cb7Schristos
4918cbf5cb7Schristos if (insn->flags & 0x10)
4928cbf5cb7Schristos printf ("|MODIFIER");
4938cbf5cb7Schristos
4948cbf5cb7Schristos printf (" %s\n", insn->name);
4958cbf5cb7Schristos }
4969573673dSchristos }
4979573673dSchristos
4989573673dSchristos for (i = 0; i < NUM_EXT_CORE; i++)
4999573673dSchristos {
5009573673dSchristos struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
5019573673dSchristos
5029573673dSchristos if (reg.name)
5038cbf5cb7Schristos printf ("CORE: 0x%04x %s %s\n", reg.number,
5048cbf5cb7Schristos ExtReadWrite_image (reg.rw),
5058cbf5cb7Schristos reg.name);
5069573673dSchristos }
5079573673dSchristos
5089573673dSchristos for (i = 0; i < NUM_EXT_COND; i++)
5099573673dSchristos if (arc_extension_map.condCodes[i])
5109573673dSchristos printf ("COND: %s\n", arc_extension_map.condCodes[i]);
5119573673dSchristos }
5128cbf5cb7Schristos
5138cbf5cb7Schristos /* For a given extension instruction generate the equivalent arc
5148cbf5cb7Schristos opcode structure. */
5158cbf5cb7Schristos
5168cbf5cb7Schristos struct arc_opcode *
arcExtMap_genOpcode(const extInstruction_t * einsn,unsigned arc_target,const char ** errmsg)5178cbf5cb7Schristos arcExtMap_genOpcode (const extInstruction_t *einsn,
5188cbf5cb7Schristos unsigned arc_target,
5198cbf5cb7Schristos const char **errmsg)
5208cbf5cb7Schristos {
5218cbf5cb7Schristos struct arc_opcode *q, *arc_ext_opcodes = NULL;
5228cbf5cb7Schristos const unsigned char *lflags_f;
5238cbf5cb7Schristos const unsigned char *lflags_ccf;
5248cbf5cb7Schristos int count;
5258cbf5cb7Schristos
5268cbf5cb7Schristos /* Check for the class to see how many instructions we generate. */
5278cbf5cb7Schristos switch (einsn->flags & ARC_SYNTAX_MASK)
5288cbf5cb7Schristos {
5298cbf5cb7Schristos case ARC_SYNTAX_3OP:
5308cbf5cb7Schristos count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
5318cbf5cb7Schristos break;
5328cbf5cb7Schristos case ARC_SYNTAX_2OP:
5338cbf5cb7Schristos count = (einsn->flags & 0x10) ? 7 : 6;
5348cbf5cb7Schristos break;
5358cbf5cb7Schristos case ARC_SYNTAX_1OP:
5368cbf5cb7Schristos count = 3;
5378cbf5cb7Schristos break;
5388cbf5cb7Schristos case ARC_SYNTAX_NOP:
5398cbf5cb7Schristos count = 1;
5408cbf5cb7Schristos break;
5418cbf5cb7Schristos default:
5428cbf5cb7Schristos count = 0;
5438cbf5cb7Schristos break;
5448cbf5cb7Schristos }
5458cbf5cb7Schristos
5468cbf5cb7Schristos /* Allocate memory. */
5478cbf5cb7Schristos arc_ext_opcodes = (struct arc_opcode *)
5488cbf5cb7Schristos xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
5498cbf5cb7Schristos
5508cbf5cb7Schristos if (arc_ext_opcodes == NULL)
5518cbf5cb7Schristos {
5528cbf5cb7Schristos *errmsg = "Virtual memory exhausted";
5538cbf5cb7Schristos return NULL;
5548cbf5cb7Schristos }
5558cbf5cb7Schristos
5568cbf5cb7Schristos /* Generate the patterns. */
5578cbf5cb7Schristos q = arc_ext_opcodes;
5588cbf5cb7Schristos
5598cbf5cb7Schristos if (einsn->suffix)
5608cbf5cb7Schristos {
5618cbf5cb7Schristos lflags_f = flags_none;
5628cbf5cb7Schristos lflags_ccf = flags_none;
5638cbf5cb7Schristos }
5648cbf5cb7Schristos else
5658cbf5cb7Schristos {
5668cbf5cb7Schristos lflags_f = flags_f;
5678cbf5cb7Schristos lflags_ccf = flags_ccf;
5688cbf5cb7Schristos }
5698cbf5cb7Schristos
5708cbf5cb7Schristos if (einsn->suffix & ARC_SUFFIX_COND)
5718cbf5cb7Schristos lflags_ccf = flags_cc;
5728cbf5cb7Schristos if (einsn->suffix & ARC_SUFFIX_FLAG)
5738cbf5cb7Schristos {
5748cbf5cb7Schristos lflags_f = flags_f;
5758cbf5cb7Schristos lflags_ccf = flags_f;
5768cbf5cb7Schristos }
5778cbf5cb7Schristos if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
5788cbf5cb7Schristos lflags_ccf = flags_ccf;
5798cbf5cb7Schristos
5808cbf5cb7Schristos if (einsn->flags & ARC_SYNTAX_2OP
5818cbf5cb7Schristos && !(einsn->flags & 0x10))
5828cbf5cb7Schristos {
5838cbf5cb7Schristos /* Regular 2OP instruction. */
5848cbf5cb7Schristos if (einsn->suffix & ARC_SUFFIX_COND)
5858cbf5cb7Schristos *errmsg = "Suffix SUFFIX_COND ignored";
5868cbf5cb7Schristos
5878cbf5cb7Schristos INSERT_XOP (q, einsn->name,
5888cbf5cb7Schristos INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
5898cbf5cb7Schristos arc_target, arg_32bit_rbrc, lflags_f);
5908cbf5cb7Schristos
5918cbf5cb7Schristos INSERT_XOP (q, einsn->name,
5928cbf5cb7Schristos INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
5938cbf5cb7Schristos arc_target, arg_32bit_zarc, lflags_f);
5948cbf5cb7Schristos
5958cbf5cb7Schristos INSERT_XOP (q, einsn->name,
5968cbf5cb7Schristos INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
5978cbf5cb7Schristos arc_target, arg_32bit_rbu6, lflags_f);
5988cbf5cb7Schristos
5998cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6008cbf5cb7Schristos INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
6018cbf5cb7Schristos arc_target, arg_32bit_zau6, lflags_f);
6028cbf5cb7Schristos
6038cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6048cbf5cb7Schristos INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
6058cbf5cb7Schristos arc_target, arg_32bit_rblimm, lflags_f);
6068cbf5cb7Schristos
6078cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6088cbf5cb7Schristos INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
6098cbf5cb7Schristos arc_target, arg_32bit_zalimm, lflags_f);
6108cbf5cb7Schristos }
6118cbf5cb7Schristos else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
6128cbf5cb7Schristos {
6138cbf5cb7Schristos /* This is actually a 3OP pattern. The first operand is
6148cbf5cb7Schristos immplied and is set to zero. */
6158cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6168cbf5cb7Schristos INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
6178cbf5cb7Schristos arc_target, arg_32bit_rbrc, lflags_f);
6188cbf5cb7Schristos
6198cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6208cbf5cb7Schristos INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
6218cbf5cb7Schristos arc_target, arg_32bit_rbu6, lflags_f);
6228cbf5cb7Schristos
6238cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6248cbf5cb7Schristos INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
6258cbf5cb7Schristos arc_target, arg_32bit_rblimm, lflags_f);
6268cbf5cb7Schristos
6278cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6288cbf5cb7Schristos INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
6298cbf5cb7Schristos arc_target, arg_32bit_limmrc, lflags_ccf);
6308cbf5cb7Schristos
6318cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6328cbf5cb7Schristos INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
6338cbf5cb7Schristos arc_target, arg_32bit_limmu6, lflags_ccf);
6348cbf5cb7Schristos
6358cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6368cbf5cb7Schristos INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
6378cbf5cb7Schristos arc_target, arg_32bit_limms12, lflags_f);
6388cbf5cb7Schristos
6398cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6408cbf5cb7Schristos INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
6418cbf5cb7Schristos arc_target, arg_32bit_limmlimm, lflags_ccf);
6428cbf5cb7Schristos }
6438cbf5cb7Schristos else if (einsn->flags & ARC_SYNTAX_3OP
6448cbf5cb7Schristos && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
6458cbf5cb7Schristos {
6468cbf5cb7Schristos /* Regular 3OP instruction. */
6478cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6488cbf5cb7Schristos INSN3OP_ABC (einsn->major, einsn->minor), MINSN3OP_ABC,
6498cbf5cb7Schristos arc_target, arg_32bit_rarbrc, lflags_f);
6508cbf5cb7Schristos
6518cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6528cbf5cb7Schristos INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
6538cbf5cb7Schristos arc_target, arg_32bit_zarbrc, lflags_f);
6548cbf5cb7Schristos
6558cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6568cbf5cb7Schristos INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
6578cbf5cb7Schristos arc_target, arg_32bit_rbrbrc, lflags_ccf);
6588cbf5cb7Schristos
6598cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6608cbf5cb7Schristos INSN3OP_ABU (einsn->major, einsn->minor), MINSN3OP_ABU,
6618cbf5cb7Schristos arc_target, arg_32bit_rarbu6, lflags_f);
6628cbf5cb7Schristos
6638cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6648cbf5cb7Schristos INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
6658cbf5cb7Schristos arc_target, arg_32bit_zarbu6, lflags_f);
6668cbf5cb7Schristos
6678cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6688cbf5cb7Schristos INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
6698cbf5cb7Schristos arc_target, arg_32bit_rbrbu6, lflags_ccf);
6708cbf5cb7Schristos
6718cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6728cbf5cb7Schristos INSN3OP_BBS (einsn->major, einsn->minor), MINSN3OP_BBS,
6738cbf5cb7Schristos arc_target, arg_32bit_rbrbs12, lflags_f);
6748cbf5cb7Schristos
6758cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6768cbf5cb7Schristos INSN3OP_ALC (einsn->major, einsn->minor), MINSN3OP_ALC,
6778cbf5cb7Schristos arc_target, arg_32bit_ralimmrc, lflags_f);
6788cbf5cb7Schristos
6798cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6808cbf5cb7Schristos INSN3OP_ABL (einsn->major, einsn->minor), MINSN3OP_ABL,
6818cbf5cb7Schristos arc_target, arg_32bit_rarblimm, lflags_f);
6828cbf5cb7Schristos
6838cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6848cbf5cb7Schristos INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC,
6858cbf5cb7Schristos arc_target, arg_32bit_zalimmrc, lflags_f);
6868cbf5cb7Schristos
6878cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6888cbf5cb7Schristos INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
6898cbf5cb7Schristos arc_target, arg_32bit_zarblimm, lflags_f);
6908cbf5cb7Schristos
6918cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6928cbf5cb7Schristos INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
6938cbf5cb7Schristos arc_target, arg_32bit_zalimmrc, lflags_ccf);
6948cbf5cb7Schristos
6958cbf5cb7Schristos INSERT_XOP (q, einsn->name,
6968cbf5cb7Schristos INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
6978cbf5cb7Schristos arc_target, arg_32bit_rbrblimm, lflags_ccf);
6988cbf5cb7Schristos
6998cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7008cbf5cb7Schristos INSN3OP_ALU (einsn->major, einsn->minor), MINSN3OP_ALU,
7018cbf5cb7Schristos arc_target, arg_32bit_ralimmu6, lflags_f);
7028cbf5cb7Schristos
7038cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7048cbf5cb7Schristos INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU,
7058cbf5cb7Schristos arc_target, arg_32bit_zalimmu6, lflags_f);
7068cbf5cb7Schristos
7078cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7088cbf5cb7Schristos INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
7098cbf5cb7Schristos arc_target, arg_32bit_zalimmu6, lflags_ccf);
7108cbf5cb7Schristos
7118cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7128cbf5cb7Schristos INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
7138cbf5cb7Schristos arc_target, arg_32bit_zalimms12, lflags_f);
7148cbf5cb7Schristos
7158cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7168cbf5cb7Schristos INSN3OP_ALL (einsn->major, einsn->minor), MINSN3OP_ALL,
7178cbf5cb7Schristos arc_target, arg_32bit_ralimmlimm, lflags_f);
7188cbf5cb7Schristos
7198cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7208cbf5cb7Schristos INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL,
7218cbf5cb7Schristos arc_target, arg_32bit_zalimmlimm, lflags_f);
7228cbf5cb7Schristos
7238cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7248cbf5cb7Schristos INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
7258cbf5cb7Schristos arc_target, arg_32bit_zalimmlimm, lflags_ccf);
7268cbf5cb7Schristos }
7278cbf5cb7Schristos else if (einsn->flags & ARC_SYNTAX_3OP)
7288cbf5cb7Schristos {
7298cbf5cb7Schristos /* 3OP instruction which accepts only zero as first
7308cbf5cb7Schristos argument. */
7318cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7328cbf5cb7Schristos INSN3OP_0BC (einsn->major, einsn->minor), MINSN3OP_0BC,
7338cbf5cb7Schristos arc_target, arg_32bit_zarbrc, lflags_f);
7348cbf5cb7Schristos
7358cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7368cbf5cb7Schristos INSN3OP_0BU (einsn->major, einsn->minor), MINSN3OP_0BU,
7378cbf5cb7Schristos arc_target, arg_32bit_zarbu6, lflags_f);
7388cbf5cb7Schristos
7398cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7408cbf5cb7Schristos INSN3OP_0LC (einsn->major, einsn->minor), MINSN3OP_0LC,
7418cbf5cb7Schristos arc_target, arg_32bit_zalimmrc, lflags_f);
7428cbf5cb7Schristos
7438cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7448cbf5cb7Schristos INSN3OP_0BL (einsn->major, einsn->minor), MINSN3OP_0BL,
7458cbf5cb7Schristos arc_target, arg_32bit_zarblimm, lflags_f);
7468cbf5cb7Schristos
7478cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7488cbf5cb7Schristos INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
7498cbf5cb7Schristos arc_target, arg_32bit_zalimmrc, lflags_ccf);
7508cbf5cb7Schristos
7518cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7528cbf5cb7Schristos INSN3OP_0LU (einsn->major, einsn->minor), MINSN3OP_0LU,
7538cbf5cb7Schristos arc_target, arg_32bit_zalimmu6, lflags_f);
7548cbf5cb7Schristos
7558cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7568cbf5cb7Schristos INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
7578cbf5cb7Schristos arc_target, arg_32bit_zalimmu6, lflags_ccf);
7588cbf5cb7Schristos
7598cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7608cbf5cb7Schristos INSN3OP_0LS (einsn->major, einsn->minor), MINSN3OP_0LS,
7618cbf5cb7Schristos arc_target, arg_32bit_zalimms12, lflags_f);
7628cbf5cb7Schristos
7638cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7648cbf5cb7Schristos INSN3OP_0LL (einsn->major, einsn->minor), MINSN3OP_0LL,
7658cbf5cb7Schristos arc_target, arg_32bit_zalimmlimm, lflags_f);
7668cbf5cb7Schristos
7678cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7688cbf5cb7Schristos INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
7698cbf5cb7Schristos arc_target, arg_32bit_zalimmlimm, lflags_ccf);
7708cbf5cb7Schristos }
7718cbf5cb7Schristos else if (einsn->flags & ARC_SYNTAX_1OP)
7728cbf5cb7Schristos {
7738cbf5cb7Schristos if (einsn->suffix & ARC_SUFFIX_COND)
7748cbf5cb7Schristos *errmsg = "Suffix SUFFIX_COND ignored";
7758cbf5cb7Schristos
7768cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7778cbf5cb7Schristos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor),
7788cbf5cb7Schristos MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f);
7798cbf5cb7Schristos
7808cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7818cbf5cb7Schristos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
7828cbf5cb7Schristos | (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6,
7838cbf5cb7Schristos lflags_f);
7848cbf5cb7Schristos
7858cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7868cbf5cb7Schristos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
7878cbf5cb7Schristos | FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm,
7888cbf5cb7Schristos lflags_f);
7898cbf5cb7Schristos
7908cbf5cb7Schristos }
7918cbf5cb7Schristos else if (einsn->flags & ARC_SYNTAX_NOP)
7928cbf5cb7Schristos {
7938cbf5cb7Schristos if (einsn->suffix & ARC_SUFFIX_COND)
7948cbf5cb7Schristos *errmsg = "Suffix SUFFIX_COND ignored";
7958cbf5cb7Schristos
7968cbf5cb7Schristos INSERT_XOP (q, einsn->name,
7978cbf5cb7Schristos INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
7988cbf5cb7Schristos | (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f);
7998cbf5cb7Schristos }
8008cbf5cb7Schristos else
8018cbf5cb7Schristos {
8028cbf5cb7Schristos *errmsg = "Unknown syntax";
8038cbf5cb7Schristos return NULL;
8048cbf5cb7Schristos }
8058cbf5cb7Schristos
8068cbf5cb7Schristos /* End marker. */
8078cbf5cb7Schristos memset (q, 0, sizeof (*arc_ext_opcodes));
8088cbf5cb7Schristos
8098cbf5cb7Schristos return arc_ext_opcodes;
8108cbf5cb7Schristos }
811