From 3ea5d02d836af7695f6d49a7492fae06d5889a9a Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Mon, 29 May 2023 01:04:57 +0300 Subject: [PATCH] ppc: decouple print_insn_powerpc_opcode routine --- opcodes/ppc-dis.c | 383 +++++++++++++++++++++++----------------------- 1 file changed, 193 insertions(+), 190 deletions(-) diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c index ea1a7ff5539..75472730ac8 100644 --- a/opcodes/ppc-dis.c +++ b/opcodes/ppc-dis.c @@ -945,6 +945,188 @@ print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info) return false; } +static void +print_insn_powerpc_opcode (struct disassemble_info *info, + bfd_vma memaddr, uint64_t insn, ppc_cpu_t dialect, + const struct powerpc_opcode *opcode) +{ + const ppc_opindex_t *opindex; + const struct powerpc_operand *operand; + enum { + need_comma = 0, + need_1space = 1, + need_2spaces = 2, + need_3spaces = 3, + need_4spaces = 4, + need_5spaces = 5, + need_6spaces = 6, + need_7spaces = 7, + need_paren + } op_separator; + bool skip_optional; + bool is_pcrel; + uint64_t d34; + int blanks; + + (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, + "%s", opcode->name); + /* gdb fprintf_styled_func doesn't return count printed. */ + blanks = 8 - strlen (opcode->name); + if (blanks <= 0) + blanks = 1; + + /* Now extract and print the operands. */ + op_separator = blanks; + skip_optional = false; + is_pcrel = false; + d34 = 0; + for (opindex = opcode->operands; *opindex != 0; opindex++) + { + int64_t value; + + operand = powerpc_operands + *opindex; + + /* If all of the optional operands past this one have their + default value, then don't print any of them. Except in + raw mode, print them all. */ + if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 + && (dialect & PPC_OPCODE_RAW) == 0) + { + if (!skip_optional) + skip_optional = skip_optional_operands (opindex, insn, + dialect, &is_pcrel); + if (skip_optional) + continue; + } + + value = operand_value_powerpc (operand, insn, dialect); + + if (op_separator == need_comma) + (*info->fprintf_styled_func) (info->stream, dis_style_text, ","); + else if (op_separator == need_paren) + (*info->fprintf_styled_func) (info->stream, dis_style_text, "("); + else + (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s", + op_separator, " "); + + /* Print the operand as directed by the flags. */ + if ((operand->flags & PPC_OPERAND_GPR) != 0 + || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0)) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "r%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_FPR) != 0) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "f%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_VR) != 0) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "v%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_VSR) != 0) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "vs%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_DMR) != 0) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "dm%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_ACC) != 0) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "a%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) + (*info->print_address_func) (memaddr + value, info); + else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) + (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); + else if ((operand->flags & PPC_OPERAND_FSL) != 0) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "fsl%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_FCR) != 0) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "fcr%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_UDI) != 0) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_CR_REG) != 0 + && (operand->flags & PPC_OPERAND_CR_BIT) == 0 + && (((dialect & PPC_OPCODE_PPC) != 0) + || ((dialect & PPC_OPCODE_VLE) != 0))) + (*info->fprintf_styled_func) (info->stream, dis_style_register, + "cr%" PRId64, value); + else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0 + && (operand->flags & PPC_OPERAND_CR_REG) == 0 + && (((dialect & PPC_OPCODE_PPC) != 0) + || ((dialect & PPC_OPCODE_VLE) != 0))) + { + static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; + int cr; + int cc; + + cr = value >> 2; + cc = value & 3; + if (cr != 0) + { + (*info->fprintf_styled_func) (info->stream, dis_style_text, + "4*"); + (*info->fprintf_styled_func) (info->stream, + dis_style_register, + "cr%d", cr); + (*info->fprintf_styled_func) (info->stream, dis_style_text, + "+"); + } + + (*info->fprintf_styled_func) (info->stream, + dis_style_sub_mnemonic, + "%s", cbnames[cc]); + } + else + { + /* An immediate, but what style? */ + enum disassembler_style style; + + if ((operand->flags & PPC_OPERAND_PARENS) != 0) + style = dis_style_address_offset; + else + style = dis_style_immediate; + + (*info->fprintf_styled_func) (info->stream, style, + "%" PRId64, value); + } + + if (operand->shift == 52) + is_pcrel = value != 0; + else if (operand->bitm == UINT64_C (0x3ffffffff)) + d34 = value; + + if (op_separator == need_paren) + (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); + + op_separator = need_comma; + if ((operand->flags & PPC_OPERAND_PARENS) != 0) + op_separator = need_paren; + } + + if (is_pcrel) + { + d34 += memaddr; + (*info->fprintf_styled_func) (info->stream, + dis_style_comment_start, + "\t# %" PRIx64, d34); + asymbol *sym = (*info->symbol_at_address_func) (d34, info); + if (sym) + (*info->fprintf_styled_func) (info->stream, dis_style_text, + " <%s>", bfd_asymbol_name (sym)); + + if (info->private_data != NULL + && info->section != NULL + && info->section->owner != NULL + && (bfd_get_file_flags (info->section->owner) + & (EXEC_P | DYNAMIC)) != 0 + && ((insn & ((-1ULL << 50) | (0x3fULL << 26))) + == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */)) + { + for (int i = 0; i < 2; i++) + if (print_got_plt (private_data (info)->special + i, d34, info)) + break; + } + } +} + /* Print a PowerPC or POWER instruction. */ static int @@ -1033,202 +1215,23 @@ print_insn_powerpc (bfd_vma memaddr, opcode = lookup_lsp (insn, dialect); } - if (opcode != NULL) + if (opcode == NULL) { - const ppc_opindex_t *opindex; - const struct powerpc_operand *operand; - enum { - need_comma = 0, - need_1space = 1, - need_2spaces = 2, - need_3spaces = 3, - need_4spaces = 4, - need_5spaces = 5, - need_6spaces = 6, - need_7spaces = 7, - need_paren - } op_separator; - bool skip_optional; - bool is_pcrel; - uint64_t d34; - int blanks; - - (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, - "%s", opcode->name); - /* gdb fprintf_styled_func doesn't return count printed. */ - blanks = 8 - strlen (opcode->name); - if (blanks <= 0) - blanks = 1; - - /* Now extract and print the operands. */ - op_separator = blanks; - skip_optional = false; - is_pcrel = false; - d34 = 0; - for (opindex = opcode->operands; *opindex != 0; opindex++) - { - int64_t value; - - operand = powerpc_operands + *opindex; - - /* If all of the optional operands past this one have their - default value, then don't print any of them. Except in - raw mode, print them all. */ - if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 - && (dialect & PPC_OPCODE_RAW) == 0) - { - if (!skip_optional) - skip_optional = skip_optional_operands (opindex, insn, - dialect, &is_pcrel); - if (skip_optional) - continue; - } - - value = operand_value_powerpc (operand, insn, dialect); - - if (op_separator == need_comma) - (*info->fprintf_styled_func) (info->stream, dis_style_text, ","); - else if (op_separator == need_paren) - (*info->fprintf_styled_func) (info->stream, dis_style_text, "("); - else - (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s", - op_separator, " "); - - /* Print the operand as directed by the flags. */ - if ((operand->flags & PPC_OPERAND_GPR) != 0 - || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0)) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "r%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_FPR) != 0) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "f%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_VR) != 0) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "v%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_VSR) != 0) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "vs%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_DMR) != 0) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "dm%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_ACC) != 0) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "a%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) - (*info->print_address_func) (memaddr + value, info); - else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) - (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); - else if ((operand->flags & PPC_OPERAND_FSL) != 0) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "fsl%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_FCR) != 0) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "fcr%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_UDI) != 0) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_CR_REG) != 0 - && (operand->flags & PPC_OPERAND_CR_BIT) == 0 - && (((dialect & PPC_OPCODE_PPC) != 0) - || ((dialect & PPC_OPCODE_VLE) != 0))) - (*info->fprintf_styled_func) (info->stream, dis_style_register, - "cr%" PRId64, value); - else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0 - && (operand->flags & PPC_OPERAND_CR_REG) == 0 - && (((dialect & PPC_OPCODE_PPC) != 0) - || ((dialect & PPC_OPCODE_VLE) != 0))) - { - static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; - int cr; - int cc; - - cr = value >> 2; - cc = value & 3; - if (cr != 0) - { - (*info->fprintf_styled_func) (info->stream, dis_style_text, - "4*"); - (*info->fprintf_styled_func) (info->stream, - dis_style_register, - "cr%d", cr); - (*info->fprintf_styled_func) (info->stream, dis_style_text, - "+"); - } - - (*info->fprintf_styled_func) (info->stream, - dis_style_sub_mnemonic, - "%s", cbnames[cc]); - } - else - { - /* An immediate, but what style? */ - enum disassembler_style style; - - if ((operand->flags & PPC_OPERAND_PARENS) != 0) - style = dis_style_address_offset; - else - style = dis_style_immediate; - - (*info->fprintf_styled_func) (info->stream, style, - "%" PRId64, value); - } - - if (operand->shift == 52) - is_pcrel = value != 0; - else if (operand->bitm == UINT64_C (0x3ffffffff)) - d34 = value; - - if (op_separator == need_paren) - (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); - - op_separator = need_comma; - if ((operand->flags & PPC_OPERAND_PARENS) != 0) - op_separator = need_paren; - } - - if (is_pcrel) + if (insn_length == 4) + (*info->fprintf_styled_func) (info->stream, + dis_style_assembler_directive, ".long"); + else { - d34 += memaddr; (*info->fprintf_styled_func) (info->stream, - dis_style_comment_start, - "\t# %" PRIx64, d34); - asymbol *sym = (*info->symbol_at_address_func) (d34, info); - if (sym) - (*info->fprintf_styled_func) (info->stream, dis_style_text, - " <%s>", bfd_asymbol_name (sym)); - - if (info->private_data != NULL - && info->section != NULL - && info->section->owner != NULL - && (bfd_get_file_flags (info->section->owner) - & (EXEC_P | DYNAMIC)) != 0 - && ((insn & ((-1ULL << 50) | (0x3fULL << 26))) - == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */)) - { - for (int i = 0; i < 2; i++) - if (print_got_plt (private_data (info)->special + i, d34, info)) - break; - } + dis_style_assembler_directive, ".word"); + insn >>= 16; } - - /* We have found and printed an instruction. */ - return insn_length; + (*info->fprintf_styled_func) (info->stream, dis_style_text, " "); + (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x", + (unsigned int) insn); } - - /* We could not find a match. */ - if (insn_length == 4) - (*info->fprintf_styled_func) (info->stream, - dis_style_assembler_directive, ".long"); else - { - (*info->fprintf_styled_func) (info->stream, - dis_style_assembler_directive, ".word"); - insn >>= 16; - } - (*info->fprintf_styled_func) (info->stream, dis_style_text, " "); - (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x", - (unsigned int) insn); - + print_insn_powerpc_opcode (info, memaddr, insn, dialect, opcode); return insn_length; } -- 2.30.2