1 /* ia64-opc.c -- Functions to access the compacted opcode table
2 Copyright (C) 1999-2019 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
= sizeof (main_table
) / sizeof (struct ia64_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];
381 /* The value of the current bit being tested. */
382 currbit
= opcode
& (((ia64_insn
) 1) << currbitnum
) ? 1 : 0;
385 /* We always perform the tests specified in the current state in
386 a particular order, falling through to the next test if the
387 previous one failed. */
388 switch (currtest
[currstatenum
])
391 currtest
[currstatenum
]++;
392 if (currbit
== 0 && (op
& 0x80))
394 /* Check for a zero bit. If this test solely checks for
395 a zero bit, we can check for up to 8 consecutive zero
396 bits (the number to check is specified by the lower 3
397 bits in the state code.)
399 If the state instruction matches, we go to the very
400 next state instruction; otherwise, try the next test. */
402 if ((op
& 0xf8) == 0x80)
404 int count
= op
& 0x7;
407 for (x
= 0; x
<= count
; x
++)
410 opcode
& (((ia64_insn
) 1) << (currbitnum
- x
)) ? 1 : 0;
418 next_op
= op_pointer
+ ((oplen
+ 7) / 8);
425 next_op
= op_pointer
+ ((oplen
+ 7) / 8);
431 /* If the bit in the instruction is one, go to the state
432 instruction specified by opval[1]. */
433 currtest
[currstatenum
]++;
434 if (currbit
&& (op
& 0x30) != 0 && ((op
& 0x30) != 0x30))
441 /* Don't care. Skip the current bit and go to the state
442 instruction specified by opval[2].
444 An encoding of 0x30 is special; this means that a 12-bit
445 offset into the ia64_dis_names[] array is specified. */
446 currtest
[currstatenum
]++;
447 if ((op
& 0x08) || ((op
& 0x30) == 0x30))
454 /* If bit 15 is set in the address of the next state, an offset
455 in the ia64_dis_names array was specified instead. We then
456 check to see if an entry in the list of opcodes matches the
457 opcode we were given; if so, we have succeeded. */
459 if ((next_op
>= 0) && (next_op
& 32768))
461 short disent
= next_op
& 32767;
469 /* Run through the list of opcodes to check, trying to find
473 int place
= ia64_dis_names
[disent
].insn_index
;
475 priority
= ia64_dis_names
[disent
].priority
;
477 if (opcode_verify (opcode
, place
, type
)
478 && priority
> found_priority
)
482 if (ia64_dis_names
[disent
].next_flag
)
494 found_disent
= disent
;
495 found_priority
= priority
;
497 /* Try the next test in this state, regardless of whether a match
502 /* next_op == -1 is "back up to the previous state".
503 next_op == -2 is "stay in this state and try the next test".
504 Otherwise, transition to the state indicated by next_op. */
509 if (currstatenum
< 0)
514 else if (next_op
>= 0)
517 bitpos
[currstatenum
] = currbitnum
- 1;
518 op_ptr
[currstatenum
] = next_op
;
519 currtest
[currstatenum
] = 0;
524 /* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
526 static struct ia64_opcode
*
527 make_ia64_opcode (ia64_insn opcode
, const char *name
, int place
, int depind
)
529 struct ia64_opcode
*res
=
530 (struct ia64_opcode
*) xmalloc (sizeof (struct ia64_opcode
));
531 res
->name
= xstrdup (name
);
532 res
->type
= main_table
[place
].opcode_type
;
533 res
->num_outputs
= main_table
[place
].num_outputs
;
534 res
->opcode
= opcode
;
535 res
->mask
= main_table
[place
].mask
;
536 res
->operands
[0] = main_table
[place
].operands
[0];
537 res
->operands
[1] = main_table
[place
].operands
[1];
538 res
->operands
[2] = main_table
[place
].operands
[2];
539 res
->operands
[3] = main_table
[place
].operands
[3];
540 res
->operands
[4] = main_table
[place
].operands
[4];
541 res
->flags
= main_table
[place
].flags
;
542 res
->ent_index
= place
;
543 res
->dependencies
= &op_dependencies
[depind
];
547 /* Determine the ia64_opcode entry for the opcode specified by INSN
548 and TYPE. If a valid entry is not found, return NULL. */
550 ia64_dis_opcode (ia64_insn insn
, enum ia64_insn_type type
)
552 int disent
= locate_opcode_ent (insn
, type
);
560 unsigned int cb
= ia64_dis_names
[disent
].completer_index
;
561 static char name
[128];
562 int place
= ia64_dis_names
[disent
].insn_index
;
563 int ci
= main_table
[place
].completers
;
564 ia64_insn tinsn
= main_table
[place
].opcode
;
566 strcpy (name
, ia64_strings
[main_table
[place
].name_index
]);
572 int cname
= completer_table
[ci
].name_index
;
574 tinsn
= apply_completer (tinsn
, ci
);
576 if (ia64_strings
[cname
][0] != '\0')
579 strcat (name
, ia64_strings
[cname
]);
583 ci
= completer_table
[ci
].subentries
;
588 ci
= completer_table
[ci
].alternative
;
596 if (tinsn
!= (insn
& main_table
[place
].mask
))
600 return make_ia64_opcode (insn
, name
, place
,
601 completer_table
[ci
].dependencies
);
605 /* Search the main_opcode table starting from PLACE for an opcode that
606 matches NAME. Return NULL if one is not found. */
608 static struct ia64_opcode
*
609 ia64_find_matching_opcode (const char *name
, short place
)
615 if (strlen (name
) > 128)
620 get_opc_prefix (&suffix
, op
);
621 name_index
= find_string_ent (op
);
627 while (main_table
[place
].name_index
== name_index
)
629 const char *curr_suffix
= suffix
;
630 ia64_insn curr_insn
= main_table
[place
].opcode
;
631 short completer
= -1;
634 if (suffix
[0] == '\0')
636 completer
= find_completer (place
, completer
, suffix
);
640 get_opc_prefix (&curr_suffix
, op
);
641 completer
= find_completer (place
, completer
, op
);
645 curr_insn
= apply_completer (curr_insn
, completer
);
647 } while (completer
!= -1 && curr_suffix
[0] != '\0');
649 if (completer
!= -1 && curr_suffix
[0] == '\0'
650 && completer_table
[completer
].terminal_completer
)
652 int depind
= completer_table
[completer
].dependencies
;
653 return make_ia64_opcode (curr_insn
, name
, place
, depind
);
663 /* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
664 if one does not exist.
666 It is the caller's responsibility to invoke ia64_free_opcode () to
667 release any resources used by the returned entry. */
670 ia64_find_next_opcode (struct ia64_opcode
*prev_ent
)
672 return ia64_find_matching_opcode (prev_ent
->name
,
673 prev_ent
->ent_index
+ 1);
676 /* Find the first opcode that matches NAME, or return NULL if it does
679 It is the caller's responsibility to invoke ia64_free_opcode () to
680 release any resources used by the returned entry. */
683 ia64_find_opcode (const char *name
)
690 if (strlen (name
) > 128)
695 get_opc_prefix (&suffix
, op
);
696 name_index
= find_string_ent (op
);
702 place
= find_main_ent (name_index
);
708 return ia64_find_matching_opcode (name
, place
);
711 /* Free any resources used by ENT. */
713 ia64_free_opcode (struct ia64_opcode
*ent
)
715 free ((void *)ent
->name
);
719 const struct ia64_dependency
*
720 ia64_find_dependency (int dep_index
)
722 dep_index
= DEP(dep_index
);
725 || dep_index
>= (int) ARRAY_SIZE (dependencies
))
728 return &dependencies
[dep_index
];