mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-12-24 07:28:47 +00:00
Use the raw instruction code and macros to identify memory instructions, extract register fields and also offset. The implementation addresses the D-form, X-form, DS-form instructions. Two main functions are added. New parse function "load_store__parse" as instruction ops parser for memory instructions. Unlike other parsers (like mov__parse), this one fills in the "multi_regs" field for source/target and new added "mem_ref" field. No other fields are set because, here there is no need to parse the disassembled code and arch specific macros will take care of extracting offset and regs which is easier and will be precise. In powerpc, all instructions with a primary opcode from 32 to 63 are memory instructions. Update "ins__find" function to have "raw_insn" also as a parameter. Reviewed-by: Kajol Jain <kjain@linux.ibm.com> Reviewed-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com> Tested-by: Kajol Jain <kjain@linux.ibm.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Akanksha J N <akanksha@linux.ibm.com> Cc: Christophe Leroy <christophe.leroy@csgroup.eu> Cc: Disha Goel <disgoel@linux.vnet.ibm.com> Cc: Hari Bathini <hbathini@linux.ibm.com> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Madhavan Srinivasan <maddy@linux.ibm.com> Cc: Segher Boessenkool <segher@kernel.crashing.org> Link: https://lore.kernel.org/lkml/20240718084358.72242-8-atrajeev@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
79 lines
1.9 KiB
C
79 lines
1.9 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <linux/compiler.h>
|
|
|
|
static struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
|
|
{
|
|
int i;
|
|
struct ins_ops *ops;
|
|
|
|
/*
|
|
* - 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;
|
|
|
|
arch__associate_ins_ops(arch, name, ops);
|
|
return ops;
|
|
}
|
|
|
|
#define PPC_OP(op) (((op) >> 26) & 0x3F)
|
|
|
|
static struct ins_ops *check_ppc_insn(u32 raw_insn)
|
|
{
|
|
int opcode = PPC_OP(raw_insn);
|
|
|
|
/*
|
|
* Instructions with opcode 32 to 63 are memory
|
|
* instructions in powerpc
|
|
*/
|
|
if ((opcode & 0x20))
|
|
return &load_store_ops;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
|
{
|
|
if (!arch->initialized) {
|
|
arch->initialized = true;
|
|
arch->associate_instruction_ops = powerpc__associate_instruction_ops;
|
|
arch->objdump.comment_char = '#';
|
|
annotate_opts.show_asm_raw = true;
|
|
}
|
|
|
|
return 0;
|
|
}
|