/* * - Interested only if instruction starts with 'b'. * - Few start with 'b', but aren't branch instructions.
*/ if (name[0] != 'b' ||
!strncmp(name, "bcd", 3) ||
!strncmp(name, "brinc", 5) ||
!strncmp(name, "bper", 4)) return NULL;
ops = &jump_ops;
i = strlen(name) - 1; if (i < 0) return NULL;
/* ignore optional hints at the end of the instructions */ if (name[i] == '+' || name[i] == '-')
i--;
if (name[i] == 'l' || (name[i] == 'a' && name[i-1] == 'l')) { /* * if the instruction ends up with 'l' or 'la', then * those are considered 'calls' since they update LR. * ... except for 'bnl' which is branch if not less than * and the absolute form of the same.
*/ if (strcmp(name, "bnl") && strcmp(name, "bnl+") &&
strcmp(name, "bnl-") && strcmp(name, "bnla") &&
strcmp(name, "bnla+") && strcmp(name, "bnla-"))
ops = &call_ops;
} if (name[i] == 'r' && name[i-1] == 'l') /* * instructions ending with 'lr' are considered to be * return instructions
*/
ops = &ret_ops;
struct insn_offset { constchar *name; int value;
};
/* * There are memory instructions with opcode 31 which are * of X Form, Example: * ldx RT,RA,RB * ______________________________________ * | 31 | RT | RA | RB | 21 |/| * -------------------------------------- * 0 6 11 16 21 30 31 * * But all instructions with opcode 31 are not memory. * Example: add RT,RA,RB * * Use bits 21 to 30 to check memory insns with 31 as opcode. * In ins_array below, for ldx instruction: * name => OP_31_XOP_LDX * value => 21
*/
/* * Instructions with opcode 32 to 63 are memory * instructions in powerpc
*/ if ((opcode & 0x20)) { /* * Set name in case of raw instruction to * opcode to be used in insn-stat
*/ if (!strlen(dl->ins.name)) {
sprintf(name_insn, "%d", opcode);
dl->ins.name = strdup(name_insn);
} return &load_store_ops;
} elseif (opcode == 31) { /* Check for memory instructions with opcode 31 */
ret = bsearch(&mem_insns_31_opcode, ins_array, ARRAY_SIZE(ins_array), sizeof(ins_array[0]), cmp_offset); if (ret) { if (!strlen(dl->ins.name))
dl->ins.name = strdup(ret->name); return &load_store_ops;
} else {
mem_insns_31_opcode.value = PPC_22_30(raw_insn);
ret = bsearch(&mem_insns_31_opcode, arithmetic_ins_op_31, ARRAY_SIZE(arithmetic_ins_op_31), sizeof(arithmetic_ins_op_31[0]), cmp_offset); if (ret != NULL) return &arithmetic_ops; /* Bits 21 to 30 has value 444 for "mr" insn ie, OR X form */ if (PPC_21_30(raw_insn) == 444) return &arithmetic_ops;
}
} else {
mem_insns_31_opcode.value = opcode;
ret = bsearch(&mem_insns_31_opcode, arithmetic_two_ops, ARRAY_SIZE(arithmetic_two_ops), sizeof(arithmetic_two_ops[0]), cmp_offset); if (ret != NULL) return &arithmetic_ops;
}
return NULL;
}
/* * Instruction tracking function to track register state moves. * Example sequence: * ld r10,264(r3) * mr r31,r3 * <<after some sequence> * ld r9,312(r31) * * Previous instruction sequence shows that register state of r3 * is moved to r31. update_insn_state_powerpc tracks these state * changes
*/ #ifdef HAVE_LIBDW_SUPPORT staticvoid update_insn_state_powerpc(struct type_state *state, struct data_loc_info *dloc, Dwarf_Die * cu_die __maybe_unused, struct disasm_line *dl)
{ struct annotated_insn_loc loc; struct annotated_op_loc *src = &loc.ops[INSN_OP_SOURCE]; struct annotated_op_loc *dst = &loc.ops[INSN_OP_TARGET]; struct type_state_reg *tsr;
u32 insn_offset = dl->al.offset;
if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0) return;
/* * Value 444 for bits 21:30 is for "mr" * instruction. "mr" is extended OR. So set the * source and destination reg correctly
*/ if (PPC_21_30(dl->raw.raw_insn) == 444) { int src_reg = src->reg1;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.