📄 ia64-opc.c
字号:
int opval[3] = {0}; int next_op; int currbit; oplen = extract_op (op_pointer, opval, &op); bitpos[currstatenum] = currbitnum; /* Skip opval[0] bits in the instruction. */ if (op & 0x40) { currbitnum -= opval[0]; } /* The value of the current bit being tested. */ currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0; next_op = -1; /* We always perform the tests specified in the current state in a particular order, falling through to the next test if the previous one failed. */ switch (currtest[currstatenum]) { case 0: currtest[currstatenum]++; if (currbit == 0 && (op & 0x80)) { /* Check for a zero bit. If this test solely checks for a zero bit, we can check for up to 8 consecutive zero bits (the number to check is specified by the lower 3 bits in the state code.) If the state instruction matches, we go to the very next state instruction; otherwise, try the next test. */ if ((op & 0xf8) == 0x80) { int count = op & 0x7; int x; for (x = 0; x <= count; x++) { int i = opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0; if (i) { break; } } if (x > count) { next_op = op_pointer + ((oplen + 7) / 8); currbitnum -= count; break; } } else if (! currbit) { next_op = op_pointer + ((oplen + 7) / 8); break; } } /* FALLTHROUGH */ case 1: /* If the bit in the instruction is one, go to the state instruction specified by opval[1]. */ currtest[currstatenum]++; if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30)) { next_op = opval[1]; break; } /* FALLTHROUGH */ case 2: /* Don't care. Skip the current bit and go to the state instruction specified by opval[2]. An encoding of 0x30 is special; this means that a 12-bit offset into the ia64_dis_names[] array is specified. */ currtest[currstatenum]++; if ((op & 0x08) || ((op & 0x30) == 0x30)) { next_op = opval[2]; break; } } /* If bit 15 is set in the address of the next state, an offset in the ia64_dis_names array was specified instead. We then check to see if an entry in the list of opcodes matches the opcode we were given; if so, we have succeeded. */ if ((next_op >= 0) && (next_op & 32768)) { short disent = next_op & 32767; short priority = -1; if (next_op > 65535) { abort (); } /* Run through the list of opcodes to check, trying to find one that matches. */ while (disent >= 0) { int place = ia64_dis_names[disent].insn_index; priority = ia64_dis_names[disent].priority; if (opcode_verify (opcode, place, type) && priority > found_priority) { break; } if (ia64_dis_names[disent].next_flag) { disent++; } else { disent = -1; } } if (disent >= 0) { found_disent = disent; found_priority = priority; } /* Try the next test in this state, regardless of whether a match was found. */ next_op = -2; } /* next_op == -1 is "back up to the previous state". next_op == -2 is "stay in this state and try the next test". Otherwise, transition to the state indicated by next_op. */ if (next_op == -1) { currstatenum--; if (currstatenum < 0) { return found_disent; } } else if (next_op >= 0) { currstatenum++; bitpos[currstatenum] = currbitnum - 1; op_ptr[currstatenum] = next_op; currtest[currstatenum] = 0; } }}/* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */static struct ia64_opcode *make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind){ struct ia64_opcode *res = (struct ia64_opcode *) malloc (sizeof (struct ia64_opcode)); res->name = strdup (name); res->type = main_table[place].opcode_type; res->num_outputs = main_table[place].num_outputs; res->opcode = opcode; res->mask = main_table[place].mask; res->operands[0] = main_table[place].operands[0]; res->operands[1] = main_table[place].operands[1]; res->operands[2] = main_table[place].operands[2]; res->operands[3] = main_table[place].operands[3]; res->operands[4] = main_table[place].operands[4]; res->flags = main_table[place].flags; res->ent_index = place; res->dependencies = &op_dependencies[depind]; return res;}/* Determine the ia64_opcode entry for the opcode specified by INSN and TYPE. If a valid entry is not found, return NULL. */struct ia64_opcode *ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type){ int disent = locate_opcode_ent (insn, type); if (disent < 0) { return NULL; } else { unsigned int cb = ia64_dis_names[disent].completer_index; static char name[128]; int place = ia64_dis_names[disent].insn_index; int ci = main_table[place].completers; ia64_insn tinsn = main_table[place].opcode; strcpy (name, ia64_strings [main_table[place].name_index]); while (cb) { if (cb & 1) { int cname = completer_table[ci].name_index; tinsn = apply_completer (tinsn, ci); if (ia64_strings[cname][0] != '\0') { strcat (name, "."); strcat (name, ia64_strings[cname]); } if (cb != 1) { ci = completer_table[ci].subentries; } } else { ci = completer_table[ci].alternative; } if (ci < 0) { abort (); } cb = cb >> 1; } if (tinsn != (insn & main_table[place].mask)) { abort (); } return make_ia64_opcode (insn, name, place, completer_table[ci].dependencies); }}/* Search the main_opcode table starting from PLACE for an opcode that matches NAME. Return NULL if one is not found. */static struct ia64_opcode *ia64_find_matching_opcode (const char *name, short place){ char op[129]; const char *suffix; short name_index; if (strlen (name) > 128) { return NULL; } suffix = name; get_opc_prefix (&suffix, op); name_index = find_string_ent (op); if (name_index < 0) { return NULL; } while (main_table[place].name_index == name_index) { const char *curr_suffix = suffix; ia64_insn curr_insn = main_table[place].opcode; short completer = -1; do { if (suffix[0] == '\0') { completer = find_completer (place, completer, suffix); } else { get_opc_prefix (&curr_suffix, op); completer = find_completer (place, completer, op); } if (completer != -1) { curr_insn = apply_completer (curr_insn, completer); } } while (completer != -1 && curr_suffix[0] != '\0'); if (completer != -1 && curr_suffix[0] == '\0' && completer_table[completer].terminal_completer) { int depind = completer_table[completer].dependencies; return make_ia64_opcode (curr_insn, name, place, depind); } else { place++; } } return NULL;}/* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL if one does not exist. It is the caller's responsibility to invoke ia64_free_opcode () to release any resources used by the returned entry. */struct ia64_opcode *ia64_find_next_opcode (struct ia64_opcode *prev_ent){ return ia64_find_matching_opcode (prev_ent->name, prev_ent->ent_index + 1);}/* Find the first opcode that matches NAME, or return NULL if it does not exist. It is the caller's responsibility to invoke ia64_free_opcode () to release any resources used by the returned entry. */struct ia64_opcode *ia64_find_opcode (const char *name){ char op[129]; const char *suffix; short place; short name_index; if (strlen (name) > 128) { return NULL; } suffix = name; get_opc_prefix (&suffix, op); name_index = find_string_ent (op); if (name_index < 0) { return NULL; } place = find_main_ent (name_index); if (place < 0) { return NULL; } return ia64_find_matching_opcode (name, place);}/* Free any resources used by ENT. */voidia64_free_opcode (struct ia64_opcode *ent){ free ((void *)ent->name); free (ent);}const struct ia64_dependency *ia64_find_dependency (int index){ index = DEP(index); if (index < 0 || index >= (int)(sizeof(dependencies) / sizeof(dependencies[0]))) return NULL; return &dependencies[index];}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -