1 /* ia64-opc.c -- Functions to access the compacted opcode table
2 Copyright 1999, 2000 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
PARAMS ((const char **, char *));
29 static short int find_string_ent
PARAMS ((const char *));
30 static short int find_main_ent
PARAMS ((short int));
31 static short int find_completer
PARAMS ((short int, short int, const char *));
32 static ia64_insn apply_completer
PARAMS ((ia64_insn
, int));
33 static int extract_op_bits
PARAMS ((int, int, int));
34 static int extract_op
PARAMS ((int, int *, unsigned int *));
35 static int opcode_verify
PARAMS ((ia64_insn
, int, enum ia64_insn_type
));
36 static int locate_opcode_ent
PARAMS ((ia64_insn
, enum ia64_insn_type
));
37 static struct ia64_opcode
*make_ia64_opcode
38 PARAMS ((ia64_insn
, const char *, int, int));
39 static struct ia64_opcode
*ia64_find_matching_opcode
40 PARAMS ((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 (ptr
, dest
)
72 char *c
= strchr (*ptr
, '.');
75 memcpy (dest
, *ptr
, c
- *ptr
);
76 dest
[c
- *ptr
] = '\0';
81 int l
= strlen (*ptr
);
82 memcpy (dest
, *ptr
, l
);
88 /* Find the index of the entry in the string table corresponding to
89 STR; return -1 if one does not exist. */
96 short end
= sizeof (ia64_strings
) / sizeof (const char *);
97 short i
= (start
+ end
) / 2;
99 if (strcmp (str
, ia64_strings
[end
- 1]) > 0)
105 int c
= strcmp (str
, ia64_strings
[i
]);
118 i
= (start
+ end
) / 2;
123 /* Find the opcode in the main opcode table whose name is STRINGINDEX, or
124 return -1 if one does not exist. */
127 find_main_ent (nameindex
)
131 short end
= sizeof (main_table
) / sizeof (struct ia64_main_table
);
132 short i
= (start
+ end
) / 2;
134 if (nameindex
< main_table
[0].name_index
135 || nameindex
> main_table
[end
- 1].name_index
)
141 if (nameindex
< main_table
[i
].name_index
)
145 else if (nameindex
== main_table
[i
].name_index
)
147 while (i
> 0 && main_table
[i
- 1].name_index
== nameindex
)
157 i
= (start
+ end
) / 2;
162 /* Find the index of the entry in the completer table that is part of
163 MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
164 return -1 if one does not exist. */
167 find_completer (main_ent
, prev_completer
, name
)
169 short prev_completer
;
172 short name_index
= find_string_ent (name
);
179 if (prev_completer
== -1)
181 prev_completer
= main_table
[main_ent
].completers
;
185 prev_completer
= completer_table
[prev_completer
].subentries
;
188 while (prev_completer
!= -1)
190 if (completer_table
[prev_completer
].name_index
== name_index
)
192 return prev_completer
;
194 prev_completer
= completer_table
[prev_completer
].alternative
;
199 /* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
200 return the result. */
203 apply_completer (opcode
, completer_index
)
207 ia64_insn mask
= completer_table
[completer_index
].mask
;
208 ia64_insn bits
= completer_table
[completer_index
].bits
;
209 int shiftamt
= (completer_table
[completer_index
].offset
& 63);
211 mask
= mask
<< shiftamt
;
212 bits
= bits
<< shiftamt
;
213 opcode
= (opcode
& ~mask
) | bits
;
217 /* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
218 the dis_table array, and return its value. (BITOFFSET is numbered
219 starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
220 first byte in OP_POINTER.) */
223 extract_op_bits (op_pointer
, bitoffset
, bits
)
230 op_pointer
+= (bitoffset
/ 8);
234 unsigned int op
= dis_table
[op_pointer
++];
235 int numb
= 8 - (bitoffset
% 8);
236 int mask
= (1 << numb
) - 1;
237 int bata
= (bits
< numb
) ? bits
: numb
;
238 int delta
= numb
- bata
;
240 res
= (res
<< bata
) | ((op
& mask
) >> delta
);
246 res
= (res
<< 8) | (dis_table
[op_pointer
++] & 255);
251 unsigned int op
= (dis_table
[op_pointer
++] & 255);
252 res
= (res
<< bits
) | (op
>> (8 - bits
));
257 /* Examine the state machine entry at OP_POINTER in the dis_table
258 array, and extract its values into OPVAL and OP. The length of the
259 state entry in bits is returned. */
262 extract_op (op_pointer
, opval
, op
)
269 *op
= dis_table
[op_pointer
];
273 opval
[0] = extract_op_bits (op_pointer
, oplen
, 5);
276 switch ((*op
) & 0x30)
280 opval
[1] = extract_op_bits (op_pointer
, oplen
, 8);
282 opval
[1] += op_pointer
;
287 opval
[1] = extract_op_bits (op_pointer
, oplen
, 16);
288 if (! (opval
[1] & 32768))
290 opval
[1] += op_pointer
;
298 opval
[2] = extract_op_bits (op_pointer
, oplen
, 12);
304 if (((*op
) & 0x08) && (((*op
) & 0x30) != 0x30))
306 opval
[2] = extract_op_bits (op_pointer
, oplen
, 16);
308 if (! (opval
[2] & 32768))
310 opval
[2] += op_pointer
;
316 /* Returns a non-zero value if the opcode in the main_table list at
317 PLACE matches OPCODE and is of type TYPE. */
320 opcode_verify (opcode
, place
, type
)
323 enum ia64_insn_type type
;
325 if (main_table
[place
].opcode_type
!= type
)
329 if (main_table
[place
].flags
330 & (IA64_OPCODE_F2_EQ_F3
| IA64_OPCODE_LEN_EQ_64MCNT
))
332 const struct ia64_operand
*o1
, *o2
;
335 if (main_table
[place
].flags
& IA64_OPCODE_F2_EQ_F3
)
337 o1
= elf64_ia64_operands
+ IA64_OPND_F2
;
338 o2
= elf64_ia64_operands
+ IA64_OPND_F3
;
339 (*o1
->extract
) (o1
, opcode
, &f2
);
340 (*o2
->extract
) (o2
, opcode
, &f3
);
346 ia64_insn len
, count
;
348 /* length must equal 64-count: */
349 o1
= elf64_ia64_operands
+ IA64_OPND_LEN6
;
350 o2
= elf64_ia64_operands
+ main_table
[place
].operands
[2];
351 (*o1
->extract
) (o1
, opcode
, &len
);
352 (*o2
->extract
) (o2
, opcode
, &count
);
353 if (len
!= 64 - count
)
360 /* Find an instruction entry in the ia64_dis_names array that matches
361 opcode OPCODE and is of type TYPE. Returns either a positive index
362 into the array, or a negative value if an entry for OPCODE could
363 not be found. Checks all matches and returns the one with the highest
367 locate_opcode_ent (opcode
, type
)
369 enum ia64_insn_type type
;
374 int currstatenum
= 0;
375 short found_disent
= -1;
376 short found_priority
= -1;
378 currtest
[currstatenum
] = 0;
379 op_ptr
[currstatenum
] = 0;
380 bitpos
[currstatenum
] = 40;
384 int op_pointer
= op_ptr
[currstatenum
];
386 int currbitnum
= bitpos
[currstatenum
];
392 oplen
= extract_op (op_pointer
, opval
, &op
);
394 bitpos
[currstatenum
] = currbitnum
;
396 /* Skip opval[0] bits in the instruction. */
399 currbitnum
-= opval
[0];
402 /* The value of the current bit being tested. */
403 currbit
= opcode
& (((ia64_insn
) 1) << currbitnum
) ? 1 : 0;
406 /* We always perform the tests specified in the current state in
407 a particular order, falling through to the next test if the
408 previous one failed. */
409 switch (currtest
[currstatenum
])
412 currtest
[currstatenum
]++;
413 if (currbit
== 0 && (op
& 0x80))
415 /* Check for a zero bit. If this test solely checks for
416 a zero bit, we can check for up to 8 consecutive zero
417 bits (the number to check is specified by the lower 3
418 bits in the state code.)
420 If the state instruction matches, we go to the very
421 next state instruction; otherwise, try the next test. */
423 if ((op
& 0xf8) == 0x80)
425 int count
= op
& 0x7;
428 for (x
= 0; x
<= count
; x
++)
431 opcode
& (((ia64_insn
) 1) << (currbitnum
- x
)) ? 1 : 0;
439 next_op
= op_pointer
+ ((oplen
+ 7) / 8);
446 next_op
= op_pointer
+ ((oplen
+ 7) / 8);
452 /* If the bit in the instruction is one, go to the state
453 instruction specified by opval[1]. */
454 currtest
[currstatenum
]++;
455 if (currbit
&& (op
& 0x30) != 0 && ((op
& 0x30) != 0x30))
462 /* Don't care. Skip the current bit and go to the state
463 instruction specified by opval[2].
465 An encoding of 0x30 is special; this means that a 12-bit
466 offset into the ia64_dis_names[] array is specified. */
467 currtest
[currstatenum
]++;
468 if ((op
& 0x08) || ((op
& 0x30) == 0x30))
475 /* If bit 15 is set in the address of the next state, an offset
476 in the ia64_dis_names array was specified instead. We then
477 check to see if an entry in the list of opcodes matches the
478 opcode we were given; if so, we have succeeded. */
480 if ((next_op
>= 0) && (next_op
& 32768))
482 short disent
= next_op
& 32767;
490 /* Run through the list of opcodes to check, trying to find
494 int place
= ia64_dis_names
[disent
].insn_index
;
496 priority
= ia64_dis_names
[disent
].priority
;
498 if (opcode_verify (opcode
, place
, type
)
499 && priority
> found_priority
)
503 if (ia64_dis_names
[disent
].next_flag
)
515 found_disent
= disent
;
516 found_priority
= priority
;
518 /* Try the next test in this state, regardless of whether a match
523 /* next_op == -1 is "back up to the previous state".
524 next_op == -2 is "stay in this state and try the next test".
525 Otherwise, transition to the state indicated by next_op. */
530 if (currstatenum
< 0)
535 else if (next_op
>= 0)
538 bitpos
[currstatenum
] = currbitnum
- 1;
539 op_ptr
[currstatenum
] = next_op
;
540 currtest
[currstatenum
] = 0;
545 /* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
547 static struct ia64_opcode
*
548 make_ia64_opcode (opcode
, name
, place
, depind
)
554 struct ia64_opcode
*res
=
555 (struct ia64_opcode
*) xmalloc (sizeof (struct ia64_opcode
));
556 res
->name
= xstrdup (name
);
557 res
->type
= main_table
[place
].opcode_type
;
558 res
->num_outputs
= main_table
[place
].num_outputs
;
559 res
->opcode
= opcode
;
560 res
->mask
= main_table
[place
].mask
;
561 res
->operands
[0] = main_table
[place
].operands
[0];
562 res
->operands
[1] = main_table
[place
].operands
[1];
563 res
->operands
[2] = main_table
[place
].operands
[2];
564 res
->operands
[3] = main_table
[place
].operands
[3];
565 res
->operands
[4] = main_table
[place
].operands
[4];
566 res
->flags
= main_table
[place
].flags
;
567 res
->ent_index
= place
;
568 res
->dependencies
= &op_dependencies
[depind
];
572 /* Determine the ia64_opcode entry for the opcode specified by INSN
573 and TYPE. If a valid entry is not found, return NULL. */
575 ia64_dis_opcode (insn
, type
)
577 enum ia64_insn_type type
;
579 int disent
= locate_opcode_ent (insn
, type
);
587 unsigned int cb
= ia64_dis_names
[disent
].completer_index
;
588 static char name
[128];
589 int place
= ia64_dis_names
[disent
].insn_index
;
590 int ci
= main_table
[place
].completers
;
591 ia64_insn tinsn
= main_table
[place
].opcode
;
593 strcpy (name
, ia64_strings
[main_table
[place
].name_index
]);
599 int cname
= completer_table
[ci
].name_index
;
601 tinsn
= apply_completer (tinsn
, ci
);
603 if (ia64_strings
[cname
][0] != '\0')
606 strcat (name
, ia64_strings
[cname
]);
610 ci
= completer_table
[ci
].subentries
;
615 ci
= completer_table
[ci
].alternative
;
623 if (tinsn
!= (insn
& main_table
[place
].mask
))
627 return make_ia64_opcode (insn
, name
, place
,
628 completer_table
[ci
].dependencies
);
632 /* Search the main_opcode table starting from PLACE for an opcode that
633 matches NAME. Return NULL if one is not found. */
635 static struct ia64_opcode
*
636 ia64_find_matching_opcode (name
, place
)
644 if (strlen (name
) > 128)
649 get_opc_prefix (&suffix
, op
);
650 name_index
= find_string_ent (op
);
656 while (main_table
[place
].name_index
== name_index
)
658 const char *curr_suffix
= suffix
;
659 ia64_insn curr_insn
= main_table
[place
].opcode
;
660 short completer
= -1;
663 if (suffix
[0] == '\0')
665 completer
= find_completer (place
, completer
, suffix
);
669 get_opc_prefix (&curr_suffix
, op
);
670 completer
= find_completer (place
, completer
, op
);
674 curr_insn
= apply_completer (curr_insn
, completer
);
676 } while (completer
!= -1 && curr_suffix
[0] != '\0');
678 if (completer
!= -1 && curr_suffix
[0] == '\0'
679 && completer_table
[completer
].terminal_completer
)
681 int depind
= completer_table
[completer
].dependencies
;
682 return make_ia64_opcode (curr_insn
, name
, place
, depind
);
692 /* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
693 if one does not exist.
695 It is the caller's responsibility to invoke ia64_free_opcode () to
696 release any resources used by the returned entry. */
699 ia64_find_next_opcode (prev_ent
)
700 struct ia64_opcode
*prev_ent
;
702 return ia64_find_matching_opcode (prev_ent
->name
,
703 prev_ent
->ent_index
+ 1);
706 /* Find the first opcode that matches NAME, or return NULL if it does
709 It is the caller's responsibility to invoke ia64_free_opcode () to
710 release any resources used by the returned entry. */
713 ia64_find_opcode (name
)
721 if (strlen (name
) > 128)
726 get_opc_prefix (&suffix
, op
);
727 name_index
= find_string_ent (op
);
733 place
= find_main_ent (name_index
);
739 return ia64_find_matching_opcode (name
, place
);
742 /* Free any resources used by ENT. */
744 ia64_free_opcode (ent
)
745 struct ia64_opcode
*ent
;
747 free ((void *)ent
->name
);
751 const struct ia64_dependency
*
752 ia64_find_dependency (index
)
758 || index
>= (int)(sizeof(dependencies
) / sizeof(dependencies
[0])))
761 return &dependencies
[index
];