1 /* ia64-opc.c -- Functions to access the compacted opcode table
2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com>
5 This file is part of the GNU opcodes library.
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this file; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
23 #include "libiberty.h"
24 #include "ia64-asmtab.h"
25 #include "ia64-asmtab.c"
27 static void get_opc_prefix (const char **, char *);
28 static short int find_string_ent (const char *);
29 static short int find_main_ent (short int);
30 static short int find_completer (short int, short int, const char *);
31 static ia64_insn
apply_completer (ia64_insn
, int);
32 static int extract_op_bits (int, int, int);
33 static int extract_op (int, int *, unsigned int *);
34 static int opcode_verify (ia64_insn
, int, enum ia64_insn_type
);
35 static int locate_opcode_ent (ia64_insn
, enum ia64_insn_type
);
36 static struct ia64_opcode
*make_ia64_opcode
37 (ia64_insn
, const char *, int, int);
38 static struct ia64_opcode
*ia64_find_matching_opcode
39 (const char *, short int);
41 const struct ia64_templ_desc ia64_templ_desc
[16] =
43 { 0, { IA64_UNIT_M
, IA64_UNIT_I
, IA64_UNIT_I
}, "MII" }, /* 0 */
44 { 2, { IA64_UNIT_M
, IA64_UNIT_I
, IA64_UNIT_I
}, "MII" },
45 { 0, { IA64_UNIT_M
, IA64_UNIT_L
, IA64_UNIT_X
}, "MLX" },
47 { 0, { IA64_UNIT_M
, IA64_UNIT_M
, IA64_UNIT_I
}, "MMI" }, /* 4 */
48 { 1, { IA64_UNIT_M
, IA64_UNIT_M
, IA64_UNIT_I
}, "MMI" },
49 { 0, { IA64_UNIT_M
, IA64_UNIT_F
, IA64_UNIT_I
}, "MFI" },
50 { 0, { IA64_UNIT_M
, IA64_UNIT_M
, IA64_UNIT_F
}, "MMF" },
51 { 0, { IA64_UNIT_M
, IA64_UNIT_I
, IA64_UNIT_B
}, "MIB" }, /* 8 */
52 { 0, { IA64_UNIT_M
, IA64_UNIT_B
, IA64_UNIT_B
}, "MBB" },
54 { 0, { IA64_UNIT_B
, IA64_UNIT_B
, IA64_UNIT_B
}, "BBB" },
55 { 0, { IA64_UNIT_M
, IA64_UNIT_M
, IA64_UNIT_B
}, "MMB" }, /* c */
57 { 0, { IA64_UNIT_M
, IA64_UNIT_F
, IA64_UNIT_B
}, "MFB" },
62 /* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST.
63 PTR will be adjusted to point to the start of the next portion
64 of the opcode, or at the NUL character. */
67 get_opc_prefix (const char **ptr
, char *dest
)
69 char *c
= strchr (*ptr
, '.');
72 memcpy (dest
, *ptr
, c
- *ptr
);
73 dest
[c
- *ptr
] = '\0';
78 int l
= strlen (*ptr
);
79 memcpy (dest
, *ptr
, l
);
85 /* Find the index of the entry in the string table corresponding to
86 STR; return -1 if one does not exist. */
89 find_string_ent (const char *str
)
92 short end
= sizeof (ia64_strings
) / sizeof (const char *);
93 short i
= (start
+ end
) / 2;
95 if (strcmp (str
, ia64_strings
[end
- 1]) > 0)
101 int c
= strcmp (str
, ia64_strings
[i
]);
114 i
= (start
+ end
) / 2;
119 /* Find the opcode in the main opcode table whose name is STRINGINDEX, or
120 return -1 if one does not exist. */
123 find_main_ent (short nameindex
)
126 short end
= ARRAY_SIZE (main_table
);
127 short i
= (start
+ end
) / 2;
129 if (nameindex
< main_table
[0].name_index
130 || nameindex
> main_table
[end
- 1].name_index
)
136 if (nameindex
< main_table
[i
].name_index
)
140 else if (nameindex
== main_table
[i
].name_index
)
142 while (i
> 0 && main_table
[i
- 1].name_index
== nameindex
)
152 i
= (start
+ end
) / 2;
157 /* Find the index of the entry in the completer table that is part of
158 MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
159 return -1 if one does not exist. */
162 find_completer (short main_ent
, short prev_completer
, const char *name
)
164 short name_index
= find_string_ent (name
);
171 if (prev_completer
== -1)
173 prev_completer
= main_table
[main_ent
].completers
;
177 prev_completer
= completer_table
[prev_completer
].subentries
;
180 while (prev_completer
!= -1)
182 if (completer_table
[prev_completer
].name_index
== name_index
)
184 return prev_completer
;
186 prev_completer
= completer_table
[prev_completer
].alternative
;
191 /* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
192 return the result. */
195 apply_completer (ia64_insn opcode
, int completer_index
)
197 ia64_insn mask
= completer_table
[completer_index
].mask
;
198 ia64_insn bits
= completer_table
[completer_index
].bits
;
199 int shiftamt
= (completer_table
[completer_index
].offset
& 63);
201 mask
= mask
<< shiftamt
;
202 bits
= bits
<< shiftamt
;
203 opcode
= (opcode
& ~mask
) | bits
;
207 /* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
208 the dis_table array, and return its value. (BITOFFSET is numbered
209 starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
210 first byte in OP_POINTER.) */
213 extract_op_bits (int op_pointer
, int bitoffset
, int bits
)
217 op_pointer
+= (bitoffset
/ 8);
221 unsigned int op
= dis_table
[op_pointer
++];
222 int numb
= 8 - (bitoffset
% 8);
223 int mask
= (1 << numb
) - 1;
224 int bata
= (bits
< numb
) ? bits
: numb
;
225 int delta
= numb
- bata
;
227 res
= (res
<< bata
) | ((op
& mask
) >> delta
);
233 res
= (res
<< 8) | (dis_table
[op_pointer
++] & 255);
238 unsigned int op
= (dis_table
[op_pointer
++] & 255);
239 res
= (res
<< bits
) | (op
>> (8 - bits
));
244 /* Examine the state machine entry at OP_POINTER in the dis_table
245 array, and extract its values into OPVAL and OP. The length of the
246 state entry in bits is returned. */
249 extract_op (int op_pointer
, int *opval
, unsigned int *op
)
253 *op
= dis_table
[op_pointer
];
257 opval
[0] = extract_op_bits (op_pointer
, oplen
, 5);
260 switch ((*op
) & 0x30)
264 opval
[1] = extract_op_bits (op_pointer
, oplen
, 8);
266 opval
[1] += op_pointer
;
271 opval
[1] = extract_op_bits (op_pointer
, oplen
, 16);
272 if (! (opval
[1] & 32768))
274 opval
[1] += op_pointer
;
282 opval
[2] = extract_op_bits (op_pointer
, oplen
, 12);
288 if (((*op
) & 0x08) && (((*op
) & 0x30) != 0x30))
290 opval
[2] = extract_op_bits (op_pointer
, oplen
, 16);
292 if (! (opval
[2] & 32768))
294 opval
[2] += op_pointer
;
300 /* Returns a non-zero value if the opcode in the main_table list at
301 PLACE matches OPCODE and is of type TYPE. */
304 opcode_verify (ia64_insn opcode
, int place
, enum ia64_insn_type type
)
306 if (main_table
[place
].opcode_type
!= type
)
310 if (main_table
[place
].flags
311 & (IA64_OPCODE_F2_EQ_F3
| IA64_OPCODE_LEN_EQ_64MCNT
))
313 const struct ia64_operand
*o1
, *o2
;
316 if (main_table
[place
].flags
& IA64_OPCODE_F2_EQ_F3
)
318 o1
= elf64_ia64_operands
+ IA64_OPND_F2
;
319 o2
= elf64_ia64_operands
+ IA64_OPND_F3
;
320 (*o1
->extract
) (o1
, opcode
, &f2
);
321 (*o2
->extract
) (o2
, opcode
, &f3
);
327 ia64_insn len
, count
;
329 /* length must equal 64-count: */
330 o1
= elf64_ia64_operands
+ IA64_OPND_LEN6
;
331 o2
= elf64_ia64_operands
+ main_table
[place
].operands
[2];
332 (*o1
->extract
) (o1
, opcode
, &len
);
333 (*o2
->extract
) (o2
, opcode
, &count
);
334 if (len
!= 64 - count
)
341 /* Find an instruction entry in the ia64_dis_names array that matches
342 opcode OPCODE and is of type TYPE. Returns either a positive index
343 into the array, or a negative value if an entry for OPCODE could
344 not be found. Checks all matches and returns the one with the highest
348 locate_opcode_ent (ia64_insn opcode
, enum ia64_insn_type type
)
353 int currstatenum
= 0;
354 short found_disent
= -1;
355 short found_priority
= -1;
357 currtest
[currstatenum
] = 0;
358 op_ptr
[currstatenum
] = 0;
359 bitpos
[currstatenum
] = 40;
363 int op_pointer
= op_ptr
[currstatenum
];
365 int currbitnum
= bitpos
[currstatenum
];
371 oplen
= extract_op (op_pointer
, opval
, &op
);
373 bitpos
[currstatenum
] = currbitnum
;
375 /* Skip opval[0] bits in the instruction. */
378 currbitnum
-= opval
[0];
384 /* The value of the current bit being tested. */
385 currbit
= opcode
& (((ia64_insn
) 1) << currbitnum
) ? 1 : 0;
388 /* We always perform the tests specified in the current state in
389 a particular order, falling through to the next test if the
390 previous one failed. */
391 switch (currtest
[currstatenum
])
394 currtest
[currstatenum
]++;
395 if (currbit
== 0 && (op
& 0x80))
397 /* Check for a zero bit. If this test solely checks for
398 a zero bit, we can check for up to 8 consecutive zero
399 bits (the number to check is specified by the lower 3
400 bits in the state code.)
402 If the state instruction matches, we go to the very
403 next state instruction; otherwise, try the next test. */
405 if ((op
& 0xf8) == 0x80)
407 int count
= op
& 0x7;
410 for (x
= 0; x
<= count
; x
++)
413 opcode
& (((ia64_insn
) 1) << (currbitnum
- x
)) ? 1 : 0;
421 next_op
= op_pointer
+ ((oplen
+ 7) / 8);
428 next_op
= op_pointer
+ ((oplen
+ 7) / 8);
434 /* If the bit in the instruction is one, go to the state
435 instruction specified by opval[1]. */
436 currtest
[currstatenum
]++;
437 if (currbit
&& (op
& 0x30) != 0 && ((op
& 0x30) != 0x30))
444 /* Don't care. Skip the current bit and go to the state
445 instruction specified by opval[2].
447 An encoding of 0x30 is special; this means that a 12-bit
448 offset into the ia64_dis_names[] array is specified. */
449 currtest
[currstatenum
]++;
450 if ((op
& 0x08) || ((op
& 0x30) == 0x30))
457 /* If bit 15 is set in the address of the next state, an offset
458 in the ia64_dis_names array was specified instead. We then
459 check to see if an entry in the list of opcodes matches the
460 opcode we were given; if so, we have succeeded. */
462 if ((next_op
>= 0) && (next_op
& 32768))
464 short disent
= next_op
& 32767;
472 /* Run through the list of opcodes to check, trying to find
476 int place
= ia64_dis_names
[disent
].insn_index
;
478 priority
= ia64_dis_names
[disent
].priority
;
480 if (opcode_verify (opcode
, place
, type
)
481 && priority
> found_priority
)
485 if (ia64_dis_names
[disent
].next_flag
)
497 found_disent
= disent
;
498 found_priority
= priority
;
500 /* Try the next test in this state, regardless of whether a match
505 /* next_op == -1 is "back up to the previous state".
506 next_op == -2 is "stay in this state and try the next test".
507 Otherwise, transition to the state indicated by next_op. */
512 if (currstatenum
< 0)
517 else if (next_op
>= 0)
520 bitpos
[currstatenum
] = currbitnum
- 1;
521 op_ptr
[currstatenum
] = next_op
;
522 currtest
[currstatenum
] = 0;
527 /* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
529 static struct ia64_opcode
*
530 make_ia64_opcode (ia64_insn opcode
, const char *name
, int place
, int depind
)
532 struct ia64_opcode
*res
=
533 (struct ia64_opcode
*) xmalloc (sizeof (struct ia64_opcode
));
534 res
->name
= xstrdup (name
);
535 res
->type
= main_table
[place
].opcode_type
;
536 res
->num_outputs
= main_table
[place
].num_outputs
;
537 res
->opcode
= opcode
;
538 res
->mask
= main_table
[place
].mask
;
539 res
->operands
[0] = main_table
[place
].operands
[0];
540 res
->operands
[1] = main_table
[place
].operands
[1];
541 res
->operands
[2] = main_table
[place
].operands
[2];
542 res
->operands
[3] = main_table
[place
].operands
[3];
543 res
->operands
[4] = main_table
[place
].operands
[4];
544 res
->flags
= main_table
[place
].flags
;
545 res
->ent_index
= place
;
546 res
->dependencies
= &op_dependencies
[depind
];
550 /* Determine the ia64_opcode entry for the opcode specified by INSN
551 and TYPE. If a valid entry is not found, return NULL. */
553 ia64_dis_opcode (ia64_insn insn
, enum ia64_insn_type type
)
555 int disent
= locate_opcode_ent (insn
, type
);
563 unsigned int cb
= ia64_dis_names
[disent
].completer_index
;
564 static char name
[128];
565 int place
= ia64_dis_names
[disent
].insn_index
;
566 int ci
= main_table
[place
].completers
;
567 ia64_insn tinsn
= main_table
[place
].opcode
;
569 strcpy (name
, ia64_strings
[main_table
[place
].name_index
]);
575 int cname
= completer_table
[ci
].name_index
;
577 tinsn
= apply_completer (tinsn
, ci
);
579 if (ia64_strings
[cname
][0] != '\0')
582 strcat (name
, ia64_strings
[cname
]);
586 ci
= completer_table
[ci
].subentries
;
591 ci
= completer_table
[ci
].alternative
;
599 if (tinsn
!= (insn
& main_table
[place
].mask
))
603 return make_ia64_opcode (insn
, name
, place
,
604 completer_table
[ci
].dependencies
);
608 /* Search the main_opcode table starting from PLACE for an opcode that
609 matches NAME. Return NULL if one is not found. */
611 static struct ia64_opcode
*
612 ia64_find_matching_opcode (const char *name
, short place
)
618 if ((unsigned) place
>= ARRAY_SIZE (main_table
))
621 if (strlen (name
) > 128)
626 get_opc_prefix (&suffix
, op
);
627 name_index
= find_string_ent (op
);
633 while (main_table
[place
].name_index
== name_index
)
635 const char *curr_suffix
= suffix
;
636 ia64_insn curr_insn
= main_table
[place
].opcode
;
637 short completer
= -1;
640 if (suffix
[0] == '\0')
642 completer
= find_completer (place
, completer
, suffix
);
646 get_opc_prefix (&curr_suffix
, op
);
647 completer
= find_completer (place
, completer
, op
);
651 curr_insn
= apply_completer (curr_insn
, completer
);
653 } while (completer
!= -1 && curr_suffix
[0] != '\0');
655 if (completer
!= -1 && curr_suffix
[0] == '\0'
656 && completer_table
[completer
].terminal_completer
)
658 int depind
= completer_table
[completer
].dependencies
;
659 return make_ia64_opcode (curr_insn
, name
, place
, depind
);
669 /* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
670 if one does not exist.
672 It is the caller's responsibility to invoke ia64_free_opcode () to
673 release any resources used by the returned entry. */
676 ia64_find_next_opcode (struct ia64_opcode
*prev_ent
)
678 return ia64_find_matching_opcode (prev_ent
->name
,
679 prev_ent
->ent_index
+ 1);
682 /* Find the first opcode that matches NAME, or return NULL if it does
685 It is the caller's responsibility to invoke ia64_free_opcode () to
686 release any resources used by the returned entry. */
689 ia64_find_opcode (const char *name
)
696 if (strlen (name
) > 128)
701 get_opc_prefix (&suffix
, op
);
702 name_index
= find_string_ent (op
);
708 place
= find_main_ent (name_index
);
714 return ia64_find_matching_opcode (name
, place
);
717 /* Free any resources used by ENT. */
719 ia64_free_opcode (struct ia64_opcode
*ent
)
721 free ((void *)ent
->name
);
725 const struct ia64_dependency
*
726 ia64_find_dependency (int dep_index
)
728 dep_index
= DEP(dep_index
);
731 || dep_index
>= (int) ARRAY_SIZE (dependencies
))
734 return &dependencies
[dep_index
];