162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/compiler.h> 362306a36Sopenharmony_ci 462306a36Sopenharmony_cistatic struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name) 562306a36Sopenharmony_ci{ 662306a36Sopenharmony_ci int i; 762306a36Sopenharmony_ci struct ins_ops *ops; 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci /* 1062306a36Sopenharmony_ci * - Interested only if instruction starts with 'b'. 1162306a36Sopenharmony_ci * - Few start with 'b', but aren't branch instructions. 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci if (name[0] != 'b' || 1462306a36Sopenharmony_ci !strncmp(name, "bcd", 3) || 1562306a36Sopenharmony_ci !strncmp(name, "brinc", 5) || 1662306a36Sopenharmony_ci !strncmp(name, "bper", 4)) 1762306a36Sopenharmony_ci return NULL; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci ops = &jump_ops; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci i = strlen(name) - 1; 2262306a36Sopenharmony_ci if (i < 0) 2362306a36Sopenharmony_ci return NULL; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci /* ignore optional hints at the end of the instructions */ 2662306a36Sopenharmony_ci if (name[i] == '+' || name[i] == '-') 2762306a36Sopenharmony_ci i--; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci if (name[i] == 'l' || (name[i] == 'a' && name[i-1] == 'l')) { 3062306a36Sopenharmony_ci /* 3162306a36Sopenharmony_ci * if the instruction ends up with 'l' or 'la', then 3262306a36Sopenharmony_ci * those are considered 'calls' since they update LR. 3362306a36Sopenharmony_ci * ... except for 'bnl' which is branch if not less than 3462306a36Sopenharmony_ci * and the absolute form of the same. 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci if (strcmp(name, "bnl") && strcmp(name, "bnl+") && 3762306a36Sopenharmony_ci strcmp(name, "bnl-") && strcmp(name, "bnla") && 3862306a36Sopenharmony_ci strcmp(name, "bnla+") && strcmp(name, "bnla-")) 3962306a36Sopenharmony_ci ops = &call_ops; 4062306a36Sopenharmony_ci } 4162306a36Sopenharmony_ci if (name[i] == 'r' && name[i-1] == 'l') 4262306a36Sopenharmony_ci /* 4362306a36Sopenharmony_ci * instructions ending with 'lr' are considered to be 4462306a36Sopenharmony_ci * return instructions 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ci ops = &ret_ops; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci arch__associate_ins_ops(arch, name, ops); 4962306a36Sopenharmony_ci return ops; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci if (!arch->initialized) { 5562306a36Sopenharmony_ci arch->initialized = true; 5662306a36Sopenharmony_ci arch->associate_instruction_ops = powerpc__associate_instruction_ops; 5762306a36Sopenharmony_ci arch->objdump.comment_char = '#'; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci return 0; 6162306a36Sopenharmony_ci} 62