?? ia64-opc.c
字號(hào):
/* ia64-opc.c -- Functions to access the compacted opcode table Copyright 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc. Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com> This file is part of GDB, GAS, and the GNU binutils. GDB, GAS, and the GNU binutils are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GDB, GAS, and the GNU binutils are distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */#include "ia64-asmtab.h"#include "ia64-asmtab.c"static void get_opc_prefix (const char **, char *);static short int find_string_ent (const char *);static short int find_main_ent (short int);static short int find_completer (short int, short int, const char *);static ia64_insn apply_completer (ia64_insn, int);static int extract_op_bits (int, int, int);static int extract_op (int, int *, unsigned int *);static int opcode_verify (ia64_insn, int, enum ia64_insn_type);static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);static struct ia64_opcode *make_ia64_opcode (ia64_insn, const char *, int, int);static struct ia64_opcode *ia64_find_matching_opcode (const char *, short int);const struct ia64_templ_desc ia64_templ_desc[16] = { { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" }, /* 0 */ { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" }, { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" }, { 0, { 0, }, "-3-" }, { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" }, /* 4 */ { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" }, { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" }, { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" }, { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" }, /* 8 */ { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" }, { 0, { 0, }, "-a-" }, { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" }, { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" }, /* c */ { 0, { 0, }, "-d-" }, { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" }, { 0, { 0, }, "-f-" }, };/* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST. PTR will be adjusted to point to the start of the next portion of the opcode, or at the NUL character. */static voidget_opc_prefix (const char **ptr, char *dest){ char *c = strchr (*ptr, '.'); if (c != NULL) { memcpy (dest, *ptr, c - *ptr); dest[c - *ptr] = '\0'; *ptr = c + 1; } else { int l = strlen (*ptr); memcpy (dest, *ptr, l); dest[l] = '\0'; *ptr += l; }}/* Find the index of the entry in the string table corresponding to STR; return -1 if one does not exist. */static shortfind_string_ent (const char *str){ short start = 0; short end = sizeof (ia64_strings) / sizeof (const char *); short i = (start + end) / 2; if (strcmp (str, ia64_strings[end - 1]) > 0) { return -1; } while (start <= end) { int c = strcmp (str, ia64_strings[i]); if (c < 0) { end = i - 1; } else if (c == 0) { return i; } else { start = i + 1; } i = (start + end) / 2; } return -1;}/* Find the opcode in the main opcode table whose name is STRINGINDEX, or return -1 if one does not exist. */static shortfind_main_ent (short nameindex){ short start = 0; short end = sizeof (main_table) / sizeof (struct ia64_main_table); short i = (start + end) / 2; if (nameindex < main_table[0].name_index || nameindex > main_table[end - 1].name_index) { return -1; } while (start <= end) { if (nameindex < main_table[i].name_index) { end = i - 1; } else if (nameindex == main_table[i].name_index) { while (i > 0 && main_table[i - 1].name_index == nameindex) { i--; } return i; } else { start = i + 1; } i = (start + end) / 2; } return -1;}/* Find the index of the entry in the completer table that is part of MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or return -1 if one does not exist. */static shortfind_completer (short main_ent, short prev_completer, const char *name){ short name_index = find_string_ent (name); if (name_index < 0) { return -1; } if (prev_completer == -1) { prev_completer = main_table[main_ent].completers; } else { prev_completer = completer_table[prev_completer].subentries; } while (prev_completer != -1) { if (completer_table[prev_completer].name_index == name_index) { return prev_completer; } prev_completer = completer_table[prev_completer].alternative; } return -1;}/* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and return the result. */static ia64_insnapply_completer (ia64_insn opcode, int completer_index){ ia64_insn mask = completer_table[completer_index].mask; ia64_insn bits = completer_table[completer_index].bits; int shiftamt = (completer_table[completer_index].offset & 63); mask = mask << shiftamt; bits = bits << shiftamt; opcode = (opcode & ~mask) | bits; return opcode;}/* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in the dis_table array, and return its value. (BITOFFSET is numbered starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the first byte in OP_POINTER.) */static intextract_op_bits (int op_pointer, int bitoffset, int bits){ int res = 0; op_pointer += (bitoffset / 8); if (bitoffset % 8) { unsigned int op = dis_table[op_pointer++]; int numb = 8 - (bitoffset % 8); int mask = (1 << numb) - 1; int bata = (bits < numb) ? bits : numb; int delta = numb - bata; res = (res << bata) | ((op & mask) >> delta); bitoffset += bata; bits -= bata; } while (bits >= 8) { res = (res << 8) | (dis_table[op_pointer++] & 255); bits -= 8; } if (bits > 0) { unsigned int op = (dis_table[op_pointer++] & 255); res = (res << bits) | (op >> (8 - bits)); } return res;}/* Examine the state machine entry at OP_POINTER in the dis_table array, and extract its values into OPVAL and OP. The length of the state entry in bits is returned. */static intextract_op (int op_pointer, int *opval, unsigned int *op){ int oplen = 5; *op = dis_table[op_pointer]; if ((*op) & 0x40) { opval[0] = extract_op_bits (op_pointer, oplen, 5); oplen += 5; } switch ((*op) & 0x30) { case 0x10: { opval[1] = extract_op_bits (op_pointer, oplen, 8); oplen += 8; opval[1] += op_pointer; break; } case 0x20: { opval[1] = extract_op_bits (op_pointer, oplen, 16); if (! (opval[1] & 32768)) { opval[1] += op_pointer; } oplen += 16; break; } case 0x30: { oplen--; opval[2] = extract_op_bits (op_pointer, oplen, 12); oplen += 12; opval[2] |= 32768; break; } } if (((*op) & 0x08) && (((*op) & 0x30) != 0x30)) { opval[2] = extract_op_bits (op_pointer, oplen, 16); oplen += 16; if (! (opval[2] & 32768)) { opval[2] += op_pointer; } } return oplen;}/* Returns a non-zero value if the opcode in the main_table list at PLACE matches OPCODE and is of type TYPE. */static intopcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type){ if (main_table[place].opcode_type != type) { return 0; } if (main_table[place].flags & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT)) { const struct ia64_operand *o1, *o2; ia64_insn f2, f3; if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3) { o1 = elf64_ia64_operands + IA64_OPND_F2; o2 = elf64_ia64_operands + IA64_OPND_F3; (*o1->extract) (o1, opcode, &f2); (*o2->extract) (o2, opcode, &f3); if (f2 != f3) return 0; } else { ia64_insn len, count; /* length must equal 64-count: */ o1 = elf64_ia64_operands + IA64_OPND_LEN6; o2 = elf64_ia64_operands + main_table[place].operands[2]; (*o1->extract) (o1, opcode, &len); (*o2->extract) (o2, opcode, &count); if (len != 64 - count) return 0; } } return 1;}/* Find an instruction entry in the ia64_dis_names array that matches opcode OPCODE and is of type TYPE. Returns either a positive index into the array, or a negative value if an entry for OPCODE could not be found. Checks all matches and returns the one with the highest priority. */static intlocate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type){ int currtest[41]; int bitpos[41]; int op_ptr[41]; int currstatenum = 0; short found_disent = -1; short found_priority = -1; currtest[currstatenum] = 0; op_ptr[currstatenum] = 0; bitpos[currstatenum] = 40; while (1) { int op_pointer = op_ptr[currstatenum]; unsigned int op; int currbitnum = bitpos[currstatenum]; int oplen;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -