1 /* ia64-opc.c -- Functions to access the compacted opcode table
2 Copyright 1999, 2000, 2003 Free Software Foundation, Inc.
3 Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com>
5 This file is part of GDB, GAS, and the GNU binutils.
7 GDB, GAS, and the GNU binutils are free software; you can redistribute
8 them and/or modify them under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either version
10 2, or (at your option) any later version.
12 GDB, GAS, and the GNU binutils are distributed in the hope that they
13 will be useful, but WITHOUT ANY WARRANTY; without even the implied
14 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 the GNU General Public 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, 59 Temple Place - Suite 330, Boston, MA
23 #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 index
)
726 || index
>= (int)(sizeof(dependencies
) / sizeof(dependencies
[0])))
729 return &dependencies
[index
];