1 /* ia64-opc.c -- Functions to access the compacted opcode table
2 Copyright 1999, 2000, 2001, 2003, 2005, 2007, 2009 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. */
24 #include "libiberty.h"
25 #include "ia64-asmtab.h"
26 #include "ia64-asmtab.c"
28 static void get_opc_prefix (const char **, char *);
29 static short int find_string_ent (const char *);
30 static short int find_main_ent (short int);
31 static short int find_completer (short int, short int, const char *);
32 static ia64_insn
apply_completer (ia64_insn
, int);
33 static int extract_op_bits (int, int, int);
34 static int extract_op (int, int *, unsigned int *);
35 static int opcode_verify (ia64_insn
, int, enum ia64_insn_type
);
36 static int locate_opcode_ent (ia64_insn
, enum ia64_insn_type
);
37 static struct ia64_opcode
*make_ia64_opcode
38 (ia64_insn
, const char *, int, int);
39 static struct ia64_opcode
*ia64_find_matching_opcode
40 (const char *, short int);
42 const struct ia64_templ_desc ia64_templ_desc
[16] =
44 { 0, { IA64_UNIT_M
, IA64_UNIT_I
, IA64_UNIT_I
}, "MII" }, /* 0 */
45 { 2, { IA64_UNIT_M
, IA64_UNIT_I
, IA64_UNIT_I
}, "MII" },
46 { 0, { IA64_UNIT_M
, IA64_UNIT_L
, IA64_UNIT_X
}, "MLX" },
48 { 0, { IA64_UNIT_M
, IA64_UNIT_M
, IA64_UNIT_I
}, "MMI" }, /* 4 */
49 { 1, { IA64_UNIT_M
, IA64_UNIT_M
, IA64_UNIT_I
}, "MMI" },
50 { 0, { IA64_UNIT_M
, IA64_UNIT_F
, IA64_UNIT_I
}, "MFI" },
51 { 0, { IA64_UNIT_M
, IA64_UNIT_M
, IA64_UNIT_F
}, "MMF" },
52 { 0, { IA64_UNIT_M
, IA64_UNIT_I
, IA64_UNIT_B
}, "MIB" }, /* 8 */
53 { 0, { IA64_UNIT_M
, IA64_UNIT_B
, IA64_UNIT_B
}, "MBB" },
55 { 0, { IA64_UNIT_B
, IA64_UNIT_B
, IA64_UNIT_B
}, "BBB" },
56 { 0, { IA64_UNIT_M
, IA64_UNIT_M
, IA64_UNIT_B
}, "MMB" }, /* c */
58 { 0, { IA64_UNIT_M
, IA64_UNIT_F
, IA64_UNIT_B
}, "MFB" },
63 /* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST.
64 PTR will be adjusted to point to the start of the next portion
65 of the opcode, or at the NUL character. */
68 get_opc_prefix (const char **ptr
, char *dest
)
70 char *c
= strchr (*ptr
, '.');
73 memcpy (dest
, *ptr
, c
- *ptr
);
74 dest
[c
- *ptr
] = '\0';
79 int l
= strlen (*ptr
);
80 memcpy (dest
, *ptr
, l
);
86 /* Find the index of the entry in the string table corresponding to
87 STR; return -1 if one does not exist. */
90 find_string_ent (const char *str
)
93 short end
= sizeof (ia64_strings
) / sizeof (const char *);
94 short i
= (start
+ end
) / 2;
96 if (strcmp (str
, ia64_strings
[end
- 1]) > 0)
102 int c
= strcmp (str
, ia64_strings
[i
]);
115 i
= (start
+ end
) / 2;
120 /* Find the opcode in the main opcode table whose name is STRINGINDEX, or
121 return -1 if one does not exist. */
124 find_main_ent (short nameindex
)
127 short end
= sizeof (main_table
) / sizeof (struct ia64_main_table
);
128 short i
= (start
+ end
) / 2;
130 if (nameindex
< main_table
[0].name_index
131 || nameindex
> main_table
[end
- 1].name_index
)
137 if (nameindex
< main_table
[i
].name_index
)
141 else if (nameindex
== main_table
[i
].name_index
)
143 while (i
> 0 && main_table
[i
- 1].name_index
== nameindex
)
153 i
= (start
+ end
) / 2;
158 /* Find the index of the entry in the completer table that is part of
159 MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
160 return -1 if one does not exist. */
163 find_completer (short main_ent
, short prev_completer
, const char *name
)
165 short name_index
= find_string_ent (name
);
172 if (prev_completer
== -1)
174 prev_completer
= main_table
[main_ent
].completers
;
178 prev_completer
= completer_table
[prev_completer
].subentries
;
181 while (prev_completer
!= -1)
183 if (completer_table
[prev_completer
].name_index
== name_index
)
185 return prev_completer
;
187 prev_completer
= completer_table
[prev_completer
].alternative
;
192 /* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
193 return the result. */
196 apply_completer (ia64_insn opcode
, int completer_index
)
198 ia64_insn mask
= completer_table
[completer_index
].mask
;
199 ia64_insn bits
= completer_table
[completer_index
].bits
;
200 int shiftamt
= (completer_table
[completer_index
].offset
& 63);
202 mask
= mask
<< shiftamt
;
203 bits
= bits
<< shiftamt
;
204 opcode
= (opcode
& ~mask
) | bits
;
208 /* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
209 the dis_table array, and return its value. (BITOFFSET is numbered
210 starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
211 first byte in OP_POINTER.) */
214 extract_op_bits (int op_pointer
, int bitoffset
, int bits
)
218 op_pointer
+= (bitoffset
/ 8);
222 unsigned int op
= dis_table
[op_pointer
++];
223 int numb
= 8 - (bitoffset
% 8);
224 int mask
= (1 << numb
) - 1;
225 int bata
= (bits
< numb
) ? bits
: numb
;
226 int delta
= numb
- bata
;
228 res
= (res
<< bata
) | ((op
& mask
) >> delta
);
234 res
= (res
<< 8) | (dis_table
[op_pointer
++] & 255);
239 unsigned int op
= (dis_table
[op_pointer
++] & 255);
240 res
= (res
<< bits
) | (op
>> (8 - bits
));
245 /* Examine the state machine entry at OP_POINTER in the dis_table
246 array, and extract its values into OPVAL and OP. The length of the
247 state entry in bits is returned. */
250 extract_op (int op_pointer
, int *opval
, unsigned int *op
)
254 *op
= dis_table
[op_pointer
];
258 opval
[0] = extract_op_bits (op_pointer
, oplen
, 5);
261 switch ((*op
) & 0x30)
265 opval
[1] = extract_op_bits (op_pointer
, oplen
, 8);
267 opval
[1] += op_pointer
;
272 opval
[1] = extract_op_bits (op_pointer
, oplen
, 16);
273 if (! (opval
[1] & 32768))
275 opval
[1] += op_pointer
;
283 opval
[2] = extract_op_bits (op_pointer
, oplen
, 12);
289 if (((*op
) & 0x08) && (((*op
) & 0x30) != 0x30))
291 opval
[2] = extract_op_bits (op_pointer
, oplen
, 16);
293 if (! (opval
[2] & 32768))
295 opval
[2] += op_pointer
;
301 /* Returns a non-zero value if the opcode in the main_table list at
302 PLACE matches OPCODE and is of type TYPE. */
305 opcode_verify (ia64_insn opcode
, int place
, enum ia64_insn_type type
)
307 if (main_table
[place
].opcode_type
!= type
)
311 if (main_table
[place
].flags
312 & (IA64_OPCODE_F2_EQ_F3
| IA64_OPCODE_LEN_EQ_64MCNT
))
314 const struct ia64_operand
*o1
, *o2
;
317 if (main_table
[place
].flags
& IA64_OPCODE_F2_EQ_F3
)
319 o1
= elf64_ia64_operands
+ IA64_OPND_F2
;
320 o2
= elf64_ia64_operands
+ IA64_OPND_F3
;
321 (*o1
->extract
) (o1
, opcode
, &f2
);
322 (*o2
->extract
) (o2
, opcode
, &f3
);
328 ia64_insn len
, count
;
330 /* length must equal 64-count: */
331 o1
= elf64_ia64_operands
+ IA64_OPND_LEN6
;
332 o2
= elf64_ia64_operands
+ main_table
[place
].operands
[2];
333 (*o1
->extract
) (o1
, opcode
, &len
);
334 (*o2
->extract
) (o2
, opcode
, &count
);
335 if (len
!= 64 - count
)
342 /* Find an instruction entry in the ia64_dis_names array that matches
343 opcode OPCODE and is of type TYPE. Returns either a positive index
344 into the array, or a negative value if an entry for OPCODE could
345 not be found. Checks all matches and returns the one with the highest
349 locate_opcode_ent (ia64_insn opcode
, enum ia64_insn_type type
)
354 int currstatenum
= 0;
355 short found_disent
= -1;
356 short found_priority
= -1;
358 currtest
[currstatenum
] = 0;
359 op_ptr
[currstatenum
] = 0;
360 bitpos
[currstatenum
] = 40;
364 int op_pointer
= op_ptr
[currstatenum
];
366 int currbitnum
= bitpos
[currstatenum
];
372 oplen
= extract_op (op_pointer
, opval
, &op
);
374 bitpos
[currstatenum
] = currbitnum
;
376 /* Skip opval[0] bits in the instruction. */
379 currbitnum
-= opval
[0];
382 /* The value of the current bit being tested. */
383 currbit
= opcode
& (((ia64_insn
) 1) << currbitnum
) ? 1 : 0;
386 /* We always perform the tests specified in the current state in
387 a particular order, falling through to the next test if the
388 previous one failed. */
389 switch (currtest
[currstatenum
])
392 currtest
[currstatenum
]++;
393 if (currbit
== 0 && (op
& 0x80))
395 /* Check for a zero bit. If this test solely checks for
396 a zero bit, we can check for up to 8 consecutive zero
397 bits (the number to check is specified by the lower 3
398 bits in the state code.)
400 If the state instruction matches, we go to the very
401 next state instruction; otherwise, try the next test. */
403 if ((op
& 0xf8) == 0x80)
405 int count
= op
& 0x7;
408 for (x
= 0; x
<= count
; x
++)
411 opcode
& (((ia64_insn
) 1) << (currbitnum
- x
)) ? 1 : 0;
419 next_op
= op_pointer
+ ((oplen
+ 7) / 8);
426 next_op
= op_pointer
+ ((oplen
+ 7) / 8);
432 /* If the bit in the instruction is one, go to the state
433 instruction specified by opval[1]. */
434 currtest
[currstatenum
]++;
435 if (currbit
&& (op
& 0x30) != 0 && ((op
& 0x30) != 0x30))
442 /* Don't care. Skip the current bit and go to the state
443 instruction specified by opval[2].
445 An encoding of 0x30 is special; this means that a 12-bit
446 offset into the ia64_dis_names[] array is specified. */
447 currtest
[currstatenum
]++;
448 if ((op
& 0x08) || ((op
& 0x30) == 0x30))
455 /* If bit 15 is set in the address of the next state, an offset
456 in the ia64_dis_names array was specified instead. We then
457 check to see if an entry in the list of opcodes matches the
458 opcode we were given; if so, we have succeeded. */
460 if ((next_op
>= 0) && (next_op
& 32768))
462 short disent
= next_op
& 32767;
470 /* Run through the list of opcodes to check, trying to find
474 int place
= ia64_dis_names
[disent
].insn_index
;
476 priority
= ia64_dis_names
[disent
].priority
;
478 if (opcode_verify (opcode
, place
, type
)
479 && priority
> found_priority
)
483 if (ia64_dis_names
[disent
].next_flag
)
495 found_disent
= disent
;
496 found_priority
= priority
;
498 /* Try the next test in this state, regardless of whether a match
503 /* next_op == -1 is "back up to the previous state".
504 next_op == -2 is "stay in this state and try the next test".
505 Otherwise, transition to the state indicated by next_op. */
510 if (currstatenum
< 0)
515 else if (next_op
>= 0)
518 bitpos
[currstatenum
] = currbitnum
- 1;
519 op_ptr
[currstatenum
] = next_op
;
520 currtest
[currstatenum
] = 0;
525 /* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
527 static struct ia64_opcode
*
528 make_ia64_opcode (ia64_insn opcode
, const char *name
, int place
, int depind
)
530 struct ia64_opcode
*res
=
531 (struct ia64_opcode
*) xmalloc (sizeof (struct ia64_opcode
));
532 res
->name
= xstrdup (name
);
533 res
->type
= main_table
[place
].opcode_type
;
534 res
->num_outputs
= main_table
[place
].num_outputs
;
535 res
->opcode
= opcode
;
536 res
->mask
= main_table
[place
].mask
;
537 res
->operands
[0] = main_table
[place
].operands
[0];
538 res
->operands
[1] = main_table
[place
].operands
[1];
539 res
->operands
[2] = main_table
[place
].operands
[2];
540 res
->operands
[3] = main_table
[place
].operands
[3];
541 res
->operands
[4] = main_table
[place
].operands
[4];
542 res
->flags
= main_table
[place
].flags
;
543 res
->ent_index
= place
;
544 res
->dependencies
= &op_dependencies
[depind
];
548 /* Determine the ia64_opcode entry for the opcode specified by INSN
549 and TYPE. If a valid entry is not found, return NULL. */
551 ia64_dis_opcode (ia64_insn insn
, enum ia64_insn_type type
)
553 int disent
= locate_opcode_ent (insn
, type
);
561 unsigned int cb
= ia64_dis_names
[disent
].completer_index
;
562 static char name
[128];
563 int place
= ia64_dis_names
[disent
].insn_index
;
564 int ci
= main_table
[place
].completers
;
565 ia64_insn tinsn
= main_table
[place
].opcode
;
567 strcpy (name
, ia64_strings
[main_table
[place
].name_index
]);
573 int cname
= completer_table
[ci
].name_index
;
575 tinsn
= apply_completer (tinsn
, ci
);
577 if (ia64_strings
[cname
][0] != '\0')
580 strcat (name
, ia64_strings
[cname
]);
584 ci
= completer_table
[ci
].subentries
;
589 ci
= completer_table
[ci
].alternative
;
597 if (tinsn
!= (insn
& main_table
[place
].mask
))
601 return make_ia64_opcode (insn
, name
, place
,
602 completer_table
[ci
].dependencies
);
606 /* Search the main_opcode table starting from PLACE for an opcode that
607 matches NAME. Return NULL if one is not found. */
609 static struct ia64_opcode
*
610 ia64_find_matching_opcode (const char *name
, short place
)
616 if (strlen (name
) > 128)
621 get_opc_prefix (&suffix
, op
);
622 name_index
= find_string_ent (op
);
628 while (main_table
[place
].name_index
== name_index
)
630 const char *curr_suffix
= suffix
;
631 ia64_insn curr_insn
= main_table
[place
].opcode
;
632 short completer
= -1;
635 if (suffix
[0] == '\0')
637 completer
= find_completer (place
, completer
, suffix
);
641 get_opc_prefix (&curr_suffix
, op
);
642 completer
= find_completer (place
, completer
, op
);
646 curr_insn
= apply_completer (curr_insn
, completer
);
648 } while (completer
!= -1 && curr_suffix
[0] != '\0');
650 if (completer
!= -1 && curr_suffix
[0] == '\0'
651 && completer_table
[completer
].terminal_completer
)
653 int depind
= completer_table
[completer
].dependencies
;
654 return make_ia64_opcode (curr_insn
, name
, place
, depind
);
664 /* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
665 if one does not exist.
667 It is the caller's responsibility to invoke ia64_free_opcode () to
668 release any resources used by the returned entry. */
671 ia64_find_next_opcode (struct ia64_opcode
*prev_ent
)
673 return ia64_find_matching_opcode (prev_ent
->name
,
674 prev_ent
->ent_index
+ 1);
677 /* Find the first opcode that matches NAME, or return NULL if it does
680 It is the caller's responsibility to invoke ia64_free_opcode () to
681 release any resources used by the returned entry. */
684 ia64_find_opcode (const char *name
)
691 if (strlen (name
) > 128)
696 get_opc_prefix (&suffix
, op
);
697 name_index
= find_string_ent (op
);
703 place
= find_main_ent (name_index
);
709 return ia64_find_matching_opcode (name
, place
);
712 /* Free any resources used by ENT. */
714 ia64_free_opcode (struct ia64_opcode
*ent
)
716 free ((void *)ent
->name
);
720 const struct ia64_dependency
*
721 ia64_find_dependency (int dep_index
)
723 dep_index
= DEP(dep_index
);
726 || dep_index
>= (int) ARRAY_SIZE (dependencies
))
729 return &dependencies
[dep_index
];