1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compiler.h>
4 static int s390_call__parse(struct arch
*arch
, struct ins_operands
*ops
,
7 char *endptr
, *tok
, *name
;
8 struct map
*map
= ms
->map
;
9 struct addr_map_symbol target
= {
10 .ms
= { .map
= map
, },
13 tok
= strchr(ops
->raw
, ',');
17 ops
->target
.addr
= strtoull(tok
+ 1, &endptr
, 16);
19 name
= strchr(endptr
, '<');
25 if (arch
->objdump
.skip_functions_char
&&
26 strchr(name
, arch
->objdump
.skip_functions_char
))
29 tok
= strchr(name
, '>');
34 ops
->target
.name
= strdup(name
);
37 if (ops
->target
.name
== NULL
)
39 target
.addr
= map__objdump_2mem(map
, ops
->target
.addr
);
41 if (maps__find_ams(ms
->maps
, &target
) == 0 &&
42 map__rip_2objdump(target
.ms
.map
, map
->map_ip(target
.ms
.map
, target
.addr
)) == ops
->target
.addr
)
43 ops
->target
.sym
= target
.ms
.sym
;
48 static int call__scnprintf(struct ins
*ins
, char *bf
, size_t size
,
49 struct ins_operands
*ops
, int max_ins_name
);
51 static struct ins_ops s390_call_ops
= {
52 .parse
= s390_call__parse
,
53 .scnprintf
= call__scnprintf
,
56 static int s390_mov__parse(struct arch
*arch __maybe_unused
,
57 struct ins_operands
*ops
,
58 struct map_symbol
*ms __maybe_unused
)
60 char *s
= strchr(ops
->raw
, ','), *target
, *endptr
;
66 ops
->source
.raw
= strdup(ops
->raw
);
69 if (ops
->source
.raw
== NULL
)
73 ops
->target
.raw
= strdup(target
);
74 if (ops
->target
.raw
== NULL
)
77 ops
->target
.addr
= strtoull(target
, &endptr
, 16);
81 s
= strchr(endptr
, '<');
84 endptr
= strchr(s
+ 1, '>');
89 ops
->target
.name
= strdup(s
+ 1);
91 if (ops
->target
.name
== NULL
)
97 zfree(&ops
->target
.raw
);
99 zfree(&ops
->source
.raw
);
104 static struct ins_ops s390_mov_ops
= {
105 .parse
= s390_mov__parse
,
106 .scnprintf
= mov__scnprintf
,
109 static struct ins_ops
*s390__associate_ins_ops(struct arch
*arch
, const char *name
)
111 struct ins_ops
*ops
= NULL
;
113 /* catch all kind of jumps */
114 if (strchr(name
, 'j') ||
115 !strncmp(name
, "bct", 3) ||
116 !strncmp(name
, "br", 2))
118 /* override call/returns */
119 if (!strcmp(name
, "bras") ||
120 !strcmp(name
, "brasl") ||
121 !strcmp(name
, "basr"))
122 ops
= &s390_call_ops
;
123 if (!strcmp(name
, "br"))
125 /* override load/store relative to PC */
126 if (!strcmp(name
, "lrl") ||
127 !strcmp(name
, "lgrl") ||
128 !strcmp(name
, "lgfrl") ||
129 !strcmp(name
, "llgfrl") ||
130 !strcmp(name
, "strl") ||
131 !strcmp(name
, "stgrl"))
135 arch__associate_ins_ops(arch
, name
, ops
);
139 static int s390__cpuid_parse(struct arch
*arch
, char *cpuid
)
142 char model
[16], model_c
[16], cpumf_v
[16], cpumf_a
[16];
146 * cpuid string format:
147 * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
149 ret
= sscanf(cpuid
, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family
, model_c
,
150 model
, cpumf_v
, cpumf_a
);
152 arch
->family
= family
;
160 static int s390__annotate_init(struct arch
*arch
, char *cpuid __maybe_unused
)
164 if (!arch
->initialized
) {
165 arch
->initialized
= true;
166 arch
->associate_instruction_ops
= s390__associate_ins_ops
;
168 if (s390__cpuid_parse(arch
, cpuid
))
169 err
= SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING
;