1 /* ARC target-dependent stuff. Extension structure access functions
2 Copyright (C) 1995-2016 Free Software Foundation, Inc.
4 This file is part of libopcodes.
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)
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.
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. */
28 #include "libiberty.h"
30 /* This module provides support for extensions to the ARC processor
34 /* Local constants. */
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
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)
52 /* These types define the information stored in the table. */
58 struct ExtAuxRegister
* next
;
61 struct ExtCoreRegister
70 struct ExtAuxRegister
* auxRegisters
;
71 struct ExtInstruction
* instructions
[INST_HASH_SIZE
];
72 struct ExtCoreRegister coreRegisters
[NUM_EXT_CORE
];
73 char* condCodes
[NUM_EXT_COND
];
79 /* Extension table. */
80 static struct arcExtMap arc_extension_map
;
85 /* A hash function used to map instructions into the table. */
86 #define INST_HASH(MAJOR, MINOR) ((((MAJOR) << 3) ^ (MINOR)) & INST_HASH_MASK)
89 /* Local functions. */
92 create_map (unsigned char *block
,
95 unsigned char *p
= block
;
97 while (p
&& p
< (block
+ length
))
99 /* p[0] == length of record
100 p[1] == type of record
103 p[3] = minor opcode (if opcode == 3)
106 For core regs and condition codes:
112 (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]). */
114 /* The sequence of records is temrinated by an "empty"
121 case EXT_INSTRUCTION
:
123 struct ExtInstruction
*insn
= XNEW (struct ExtInstruction
);
126 struct ExtInstruction
**bucket
=
127 &arc_extension_map
.instructions
[INST_HASH (major
, minor
)];
129 insn
->name
= xstrdup ((char *) (p
+ 5));
133 insn
->next
= *bucket
;
141 case EXT_CORE_REGISTER
:
143 unsigned char number
= p
[2];
144 char* name
= (char *) (p
+ 3);
147 coreRegisters
[number
- FIRST_EXTENSION_CORE_REGISTER
].number
150 coreRegisters
[number
- FIRST_EXTENSION_CORE_REGISTER
].rw
153 coreRegisters
[number
- FIRST_EXTENSION_CORE_REGISTER
].name
158 case EXT_LONG_CORE_REGISTER
:
160 unsigned char number
= p
[2];
161 char* name
= (char *) (p
+ 7);
162 enum ExtReadWrite rw
= p
[6];
165 coreRegisters
[number
- FIRST_EXTENSION_CORE_REGISTER
].number
168 coreRegisters
[number
- FIRST_EXTENSION_CORE_REGISTER
].rw
171 coreRegisters
[number
- FIRST_EXTENSION_CORE_REGISTER
].name
177 char *cc_name
= xstrdup ((char *) (p
+ 3));
180 condCodes
[p
[2] - FIRST_EXTENSION_CONDITION_CODE
]
185 case EXT_AUX_REGISTER
:
187 /* Trickier -- need to store linked list of these. */
188 struct ExtAuxRegister
*newAuxRegister
189 = XNEW (struct ExtAuxRegister
);
190 char *aux_name
= xstrdup ((char *) (p
+ 6));
192 newAuxRegister
->name
= aux_name
;
193 newAuxRegister
->address
= (p
[2] << 24) | (p
[3] << 16)
194 | (p
[4] << 8) | p
[5];
195 newAuxRegister
->next
= arc_extension_map
.auxRegisters
;
196 arc_extension_map
.auxRegisters
= newAuxRegister
;
204 p
+= p
[0]; /* Move on to next record. */
209 /* Free memory that has been allocated for the extensions. */
214 struct ExtAuxRegister
*r
;
217 /* Free auxiliary registers. */
218 r
= arc_extension_map
.auxRegisters
;
221 /* N.B. after r has been freed, r->next is invalid! */
222 struct ExtAuxRegister
* next
= r
->next
;
229 /* Free instructions. */
230 for (i
= 0; i
< INST_HASH_SIZE
; i
++)
232 struct ExtInstruction
*insn
= arc_extension_map
.instructions
[i
];
236 /* N.B. after insn has been freed, insn->next is invalid! */
237 struct ExtInstruction
*next
= insn
->next
;
245 /* Free core registers. */
246 for (i
= 0; i
< NUM_EXT_CORE
; i
++)
248 if (arc_extension_map
.coreRegisters
[i
].name
)
249 free (arc_extension_map
.coreRegisters
[i
].name
);
252 /* Free condition codes. */
253 for (i
= 0; i
< NUM_EXT_COND
; i
++)
255 if (arc_extension_map
.condCodes
[i
])
256 free (arc_extension_map
.condCodes
[i
]);
259 memset (&arc_extension_map
, 0, sizeof (arc_extension_map
));
264 ExtReadWrite_image (enum ExtReadWrite val
)
268 case REG_INVALID
: return "INVALID";
269 case REG_READ
: return "RO";
270 case REG_WRITE
: return "WO";
271 case REG_READWRITE
: return "R/W";
272 default : return "???";
277 /* Externally visible functions. */
279 /* Get the name of an extension instruction. */
281 const extInstruction_t
*
282 arcExtMap_insn (int opcode
, int insn
)
284 /* Here the following tasks need to be done. First of all, the
285 opcode stored in the Extension Map is the real opcode. However,
286 the subopcode stored in the instruction to be disassembled is
287 mangled. We pass (in minor opcode), the instruction word. Here
288 we will un-mangle it and get the real subopcode which we can look
289 for in the Extension Map. This function is used both for the
290 ARCTangent and the ARCompact, so we would also need some sort of
291 a way to distinguish between the two architectures. This is
292 because the ARCTangent does not do any of this mangling so we
293 have no issues there. */
295 /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI. If it is 1
296 then use iiiiIi. Now, if P is 3 then check M[5:5] and if it is 0
297 then un-mangle using iiiiiI else iiiiii. */
300 extInstruction_t
*temp
;
302 /* 16-bit instructions. */
303 if (0x08 <= opcode
&& opcode
<= 0x0b)
305 unsigned char b
, c
, i
;
307 b
= (insn
& 0x0700) >> 8;
308 c
= (insn
& 0x00e0) >> 5;
314 minor
= (c
== 0x07) ? b
: c
;
316 /* 32-bit instructions. */
319 unsigned char I
, A
, B
;
321 I
= (insn
& 0x003f0000) >> 16;
322 A
= (insn
& 0x0000003f);
323 B
= ((insn
& 0x07000000) >> 24) | ((insn
& 0x00007000) >> 9);
338 minor
= (I
>> 1) | ((I
& 0x1) << 5);
341 minor
= (I
>> 1) | (I
& 0x1) | ((I
& 0x2) << 4);
356 temp
= arc_extension_map
.instructions
[INST_HASH (opcode
, minor
)];
359 if ((temp
->major
== opcode
) && (temp
->minor
== minor
))
369 /* Get the name of an extension core register. */
372 arcExtMap_coreRegName (int regnum
)
374 if (regnum
< FIRST_EXTENSION_CORE_REGISTER
375 || regnum
> LAST_EXTENSION_CORE_REGISTER
)
377 return arc_extension_map
.
378 coreRegisters
[regnum
- FIRST_EXTENSION_CORE_REGISTER
].name
;
381 /* Get the access mode of an extension core register. */
384 arcExtMap_coreReadWrite (int regnum
)
386 if (regnum
< FIRST_EXTENSION_CORE_REGISTER
387 || regnum
> LAST_EXTENSION_CORE_REGISTER
)
389 return arc_extension_map
.
390 coreRegisters
[regnum
- FIRST_EXTENSION_CORE_REGISTER
].rw
;
393 /* Get the name of an extension condition code. */
396 arcExtMap_condCodeName (int code
)
398 if (code
< FIRST_EXTENSION_CONDITION_CODE
399 || code
> LAST_EXTENSION_CONDITION_CODE
)
401 return arc_extension_map
.
402 condCodes
[code
- FIRST_EXTENSION_CONDITION_CODE
];
405 /* Get the name of an extension auxiliary register. */
408 arcExtMap_auxRegName (long address
)
410 /* Walk the list of auxiliary register names and find the name. */
411 struct ExtAuxRegister
*r
;
413 for (r
= arc_extension_map
.auxRegisters
; r
; r
= r
->next
)
415 if (r
->address
== address
)
416 return (const char *)r
->name
;
421 /* Load extensions described in .arcextmap and
422 .gnu.linkonce.arcextmap.* ELF section. */
425 build_ARC_extmap (bfd
*text_bfd
)
429 /* The map is built each time gdb loads an executable file - so free
430 any existing map, as the map defined by the new file may differ
434 for (sect
= text_bfd
->sections
; sect
!= NULL
; sect
= sect
->next
)
435 if (!strncmp (sect
->name
,
436 ".gnu.linkonce.arcextmap.",
437 sizeof (".gnu.linkonce.arcextmap.") - 1)
438 || !strcmp (sect
->name
,".arcextmap"))
440 bfd_size_type count
= bfd_get_section_size (sect
);
441 unsigned char* buffer
= xmalloc (count
);
445 if (bfd_get_section_contents (text_bfd
, sect
, buffer
, 0, count
))
446 create_map (buffer
, count
);
452 /* Debug function used to dump the ARC information fount in arcextmap
456 dump_ARC_extmap (void)
458 struct ExtAuxRegister
*r
;
461 r
= arc_extension_map
.auxRegisters
;
465 printf ("AUX : %s %ld\n", r
->name
, r
->address
);
469 for (i
= 0; i
< INST_HASH_SIZE
; i
++)
471 struct ExtInstruction
*insn
;
473 for (insn
= arc_extension_map
.instructions
[i
];
474 insn
!= NULL
; insn
= insn
->next
)
476 printf ("INST: 0x%02x 0x%02x ", insn
->major
, insn
->minor
);
477 if (insn
->flags
& ARC_SYNTAX_2OP
)
478 printf ("SYNTAX_2OP");
479 else if (insn
->flags
& ARC_SYNTAX_3OP
)
480 printf ("SYNTAX_3OP");
482 printf ("SYNTAX_UNK");
484 if (insn
->flags
& 0x10)
485 printf ("|MODIFIER");
487 printf (" %s\n", insn
->name
);
491 for (i
= 0; i
< NUM_EXT_CORE
; i
++)
493 struct ExtCoreRegister reg
= arc_extension_map
.coreRegisters
[i
];
496 printf ("CORE: 0x%04x %s %s\n", reg
.number
,
497 ExtReadWrite_image (reg
.rw
),
501 for (i
= 0; i
< NUM_EXT_COND
; i
++)
502 if (arc_extension_map
.condCodes
[i
])
503 printf ("COND: %s\n", arc_extension_map
.condCodes
[i
]);
506 /* For a given extension instruction generate the equivalent arc
510 arcExtMap_genOpcode (const extInstruction_t
*einsn
,
514 struct arc_opcode
*q
, *arc_ext_opcodes
= NULL
;
515 const unsigned char *lflags_f
;
516 const unsigned char *lflags_ccf
;
519 /* Check for the class to see how many instructions we generate. */
520 switch (einsn
->flags
& (ARC_SYNTAX_3OP
| ARC_SYNTAX_2OP
))
523 count
= (einsn
->modsyn
& ARC_OP1_MUST_BE_IMM
) ? 10 : 20;
526 count
= (einsn
->flags
& 0x10) ? 7 : 6;
533 /* Allocate memory. */
534 arc_ext_opcodes
= (struct arc_opcode
*)
535 xmalloc ((count
+ 1) * sizeof (*arc_ext_opcodes
));
537 if (arc_ext_opcodes
== NULL
)
539 *errmsg
= "Virtual memory exhausted";
543 /* Generate the patterns. */
548 lflags_f
= flags_none
;
549 lflags_ccf
= flags_none
;
554 lflags_ccf
= flags_ccf
;
557 if (einsn
->suffix
& ARC_SUFFIX_COND
)
558 lflags_ccf
= flags_cc
;
559 if (einsn
->suffix
& ARC_SUFFIX_FLAG
)
562 lflags_ccf
= flags_f
;
564 if (einsn
->suffix
& (ARC_SUFFIX_FLAG
| ARC_SUFFIX_COND
))
565 lflags_ccf
= flags_ccf
;
567 if (einsn
->flags
& ARC_SYNTAX_2OP
568 && !(einsn
->flags
& 0x10))
570 /* Regular 2OP instruction. */
571 if (einsn
->suffix
& ARC_SUFFIX_COND
)
572 *errmsg
= "Suffix SUFFIX_COND ignored";
574 INSERT_XOP (q
, einsn
->name
,
575 INSN2OP_BC (einsn
->major
, einsn
->minor
), MINSN2OP_BC
,
576 arc_target
, arg_32bit_rbrc
, lflags_f
);
578 INSERT_XOP (q
, einsn
->name
,
579 INSN2OP_0C (einsn
->major
, einsn
->minor
), MINSN2OP_0C
,
580 arc_target
, arg_32bit_zarc
, lflags_f
);
582 INSERT_XOP (q
, einsn
->name
,
583 INSN2OP_BU (einsn
->major
, einsn
->minor
), MINSN2OP_BU
,
584 arc_target
, arg_32bit_rbu6
, lflags_f
);
586 INSERT_XOP (q
, einsn
->name
,
587 INSN2OP_0U (einsn
->major
, einsn
->minor
), MINSN2OP_0U
,
588 arc_target
, arg_32bit_zau6
, lflags_f
);
590 INSERT_XOP (q
, einsn
->name
,
591 INSN2OP_BL (einsn
->major
, einsn
->minor
), MINSN2OP_BL
,
592 arc_target
, arg_32bit_rblimm
, lflags_f
);
594 INSERT_XOP (q
, einsn
->name
,
595 INSN2OP_0L (einsn
->major
, einsn
->minor
), MINSN2OP_0L
,
596 arc_target
, arg_32bit_zalimm
, lflags_f
);
598 else if (einsn
->flags
& (0x10 | ARC_SYNTAX_2OP
))
600 /* This is actually a 3OP pattern. The first operand is
601 immplied and is set to zero. */
602 INSERT_XOP (q
, einsn
->name
,
603 INSN3OP_0BC (einsn
->major
, einsn
->minor
), MINSN3OP_0BC
,
604 arc_target
, arg_32bit_rbrc
, lflags_f
);
606 INSERT_XOP (q
, einsn
->name
,
607 INSN3OP_0BU (einsn
->major
, einsn
->minor
), MINSN3OP_0BU
,
608 arc_target
, arg_32bit_rbu6
, lflags_f
);
610 INSERT_XOP (q
, einsn
->name
,
611 INSN3OP_0BL (einsn
->major
, einsn
->minor
), MINSN3OP_0BL
,
612 arc_target
, arg_32bit_rblimm
, lflags_f
);
614 INSERT_XOP (q
, einsn
->name
,
615 INSN3OP_C0LC (einsn
->major
, einsn
->minor
), MINSN3OP_C0LC
,
616 arc_target
, arg_32bit_limmrc
, lflags_ccf
);
618 INSERT_XOP (q
, einsn
->name
,
619 INSN3OP_C0LU (einsn
->major
, einsn
->minor
), MINSN3OP_C0LU
,
620 arc_target
, arg_32bit_limmu6
, lflags_ccf
);
622 INSERT_XOP (q
, einsn
->name
,
623 INSN3OP_0LS (einsn
->major
, einsn
->minor
), MINSN3OP_0LS
,
624 arc_target
, arg_32bit_limms12
, lflags_f
);
626 INSERT_XOP (q
, einsn
->name
,
627 INSN3OP_C0LL (einsn
->major
, einsn
->minor
), MINSN3OP_C0LL
,
628 arc_target
, arg_32bit_limmlimm
, lflags_ccf
);
630 else if (einsn
->flags
& ARC_SYNTAX_3OP
631 && !(einsn
->modsyn
& ARC_OP1_MUST_BE_IMM
))
633 /* Regular 3OP instruction. */
634 INSERT_XOP (q
, einsn
->name
,
635 INSN3OP_ABC (einsn
->major
, einsn
->minor
), MINSN3OP_ABC
,
636 arc_target
, arg_32bit_rarbrc
, lflags_f
);
638 INSERT_XOP (q
, einsn
->name
,
639 INSN3OP_0BC (einsn
->major
, einsn
->minor
), MINSN3OP_0BC
,
640 arc_target
, arg_32bit_zarbrc
, lflags_f
);
642 INSERT_XOP (q
, einsn
->name
,
643 INSN3OP_CBBC (einsn
->major
, einsn
->minor
), MINSN3OP_CBBC
,
644 arc_target
, arg_32bit_rbrbrc
, lflags_ccf
);
646 INSERT_XOP (q
, einsn
->name
,
647 INSN3OP_ABU (einsn
->major
, einsn
->minor
), MINSN3OP_ABU
,
648 arc_target
, arg_32bit_rarbu6
, lflags_f
);
650 INSERT_XOP (q
, einsn
->name
,
651 INSN3OP_0BU (einsn
->major
, einsn
->minor
), MINSN3OP_0BU
,
652 arc_target
, arg_32bit_zarbu6
, lflags_f
);
654 INSERT_XOP (q
, einsn
->name
,
655 INSN3OP_CBBU (einsn
->major
, einsn
->minor
), MINSN3OP_CBBU
,
656 arc_target
, arg_32bit_rbrbu6
, lflags_ccf
);
658 INSERT_XOP (q
, einsn
->name
,
659 INSN3OP_BBS (einsn
->major
, einsn
->minor
), MINSN3OP_BBS
,
660 arc_target
, arg_32bit_rbrbs12
, lflags_f
);
662 INSERT_XOP (q
, einsn
->name
,
663 INSN3OP_ALC (einsn
->major
, einsn
->minor
), MINSN3OP_ALC
,
664 arc_target
, arg_32bit_ralimmrc
, lflags_f
);
666 INSERT_XOP (q
, einsn
->name
,
667 INSN3OP_ABL (einsn
->major
, einsn
->minor
), MINSN3OP_ABL
,
668 arc_target
, arg_32bit_rarblimm
, lflags_f
);
670 INSERT_XOP (q
, einsn
->name
,
671 INSN3OP_0LC (einsn
->major
, einsn
->minor
), MINSN3OP_0LC
,
672 arc_target
, arg_32bit_zalimmrc
, lflags_f
);
674 INSERT_XOP (q
, einsn
->name
,
675 INSN3OP_0BL (einsn
->major
, einsn
->minor
), MINSN3OP_0BL
,
676 arc_target
, arg_32bit_zarblimm
, lflags_f
);
678 INSERT_XOP (q
, einsn
->name
,
679 INSN3OP_C0LC (einsn
->major
, einsn
->minor
), MINSN3OP_C0LC
,
680 arc_target
, arg_32bit_zalimmrc
, lflags_ccf
);
682 INSERT_XOP (q
, einsn
->name
,
683 INSN3OP_CBBL (einsn
->major
, einsn
->minor
), MINSN3OP_CBBL
,
684 arc_target
, arg_32bit_rbrblimm
, lflags_ccf
);
686 INSERT_XOP (q
, einsn
->name
,
687 INSN3OP_ALU (einsn
->major
, einsn
->minor
), MINSN3OP_ALU
,
688 arc_target
, arg_32bit_ralimmu6
, lflags_f
);
690 INSERT_XOP (q
, einsn
->name
,
691 INSN3OP_0LU (einsn
->major
, einsn
->minor
), MINSN3OP_0LU
,
692 arc_target
, arg_32bit_zalimmu6
, lflags_f
);
694 INSERT_XOP (q
, einsn
->name
,
695 INSN3OP_C0LU (einsn
->major
, einsn
->minor
), MINSN3OP_C0LU
,
696 arc_target
, arg_32bit_zalimmu6
, lflags_ccf
);
698 INSERT_XOP (q
, einsn
->name
,
699 INSN3OP_0LS (einsn
->major
, einsn
->minor
), MINSN3OP_0LS
,
700 arc_target
, arg_32bit_zalimms12
, lflags_f
);
702 INSERT_XOP (q
, einsn
->name
,
703 INSN3OP_ALL (einsn
->major
, einsn
->minor
), MINSN3OP_ALL
,
704 arc_target
, arg_32bit_ralimmlimm
, lflags_f
);
706 INSERT_XOP (q
, einsn
->name
,
707 INSN3OP_0LL (einsn
->major
, einsn
->minor
), MINSN3OP_0LL
,
708 arc_target
, arg_32bit_zalimmlimm
, lflags_f
);
710 INSERT_XOP (q
, einsn
->name
,
711 INSN3OP_C0LL (einsn
->major
, einsn
->minor
), MINSN3OP_C0LL
,
712 arc_target
, arg_32bit_zalimmlimm
, lflags_ccf
);
714 else if (einsn
->flags
& ARC_SYNTAX_3OP
)
716 /* 3OP instruction which accepts only zero as first
718 INSERT_XOP (q
, einsn
->name
,
719 INSN3OP_0BC (einsn
->major
, einsn
->minor
), MINSN3OP_0BC
,
720 arc_target
, arg_32bit_zarbrc
, lflags_f
);
722 INSERT_XOP (q
, einsn
->name
,
723 INSN3OP_0BU (einsn
->major
, einsn
->minor
), MINSN3OP_0BU
,
724 arc_target
, arg_32bit_zarbu6
, lflags_f
);
726 INSERT_XOP (q
, einsn
->name
,
727 INSN3OP_0LC (einsn
->major
, einsn
->minor
), MINSN3OP_0LC
,
728 arc_target
, arg_32bit_zalimmrc
, lflags_f
);
730 INSERT_XOP (q
, einsn
->name
,
731 INSN3OP_0BL (einsn
->major
, einsn
->minor
), MINSN3OP_0BL
,
732 arc_target
, arg_32bit_zarblimm
, lflags_f
);
734 INSERT_XOP (q
, einsn
->name
,
735 INSN3OP_C0LC (einsn
->major
, einsn
->minor
), MINSN3OP_C0LC
,
736 arc_target
, arg_32bit_zalimmrc
, lflags_ccf
);
738 INSERT_XOP (q
, einsn
->name
,
739 INSN3OP_0LU (einsn
->major
, einsn
->minor
), MINSN3OP_0LU
,
740 arc_target
, arg_32bit_zalimmu6
, lflags_f
);
742 INSERT_XOP (q
, einsn
->name
,
743 INSN3OP_C0LU (einsn
->major
, einsn
->minor
), MINSN3OP_C0LU
,
744 arc_target
, arg_32bit_zalimmu6
, lflags_ccf
);
746 INSERT_XOP (q
, einsn
->name
,
747 INSN3OP_0LS (einsn
->major
, einsn
->minor
), MINSN3OP_0LS
,
748 arc_target
, arg_32bit_zalimms12
, lflags_f
);
750 INSERT_XOP (q
, einsn
->name
,
751 INSN3OP_0LL (einsn
->major
, einsn
->minor
), MINSN3OP_0LL
,
752 arc_target
, arg_32bit_zalimmlimm
, lflags_f
);
754 INSERT_XOP (q
, einsn
->name
,
755 INSN3OP_C0LL (einsn
->major
, einsn
->minor
), MINSN3OP_C0LL
,
756 arc_target
, arg_32bit_zalimmlimm
, lflags_ccf
);
760 *errmsg
= "Unknown syntax";
765 memset (q
, 0, sizeof (*arc_ext_opcodes
));
767 return arc_ext_opcodes
;