1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2215a0d30SArnaldo Carvalho de Melo #include <stdbool.h>
3215a0d30SArnaldo Carvalho de Melo #include <stdlib.h>
4215a0d30SArnaldo Carvalho de Melo #include <stdint.h>
5215a0d30SArnaldo Carvalho de Melo #include <string.h>
6215a0d30SArnaldo Carvalho de Melo #include <stdio.h>
7bcc84ec6SStephane Eranian #include "util/debug.h"
84b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
9215a0d30SArnaldo Carvalho de Melo #include "util/perf_regs.h"
10bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
11bcc84ec6SStephane Eranian 
12aeea9062SKan Liang static int
__parse_regs(const struct option * opt,const char * str,int unset,bool intr)13aeea9062SKan Liang __parse_regs(const struct option *opt, const char *str, int unset, bool intr)
14bcc84ec6SStephane Eranian {
15bcc84ec6SStephane Eranian 	uint64_t *mode = (uint64_t *)opt->value;
1642466b9fSIan Rogers 	const struct sample_reg *r = NULL;
17bcc84ec6SStephane Eranian 	char *s, *os = NULL, *p;
18bcc84ec6SStephane Eranian 	int ret = -1;
19af785e75SKan Liang 	uint64_t mask;
20bcc84ec6SStephane Eranian 
21bcc84ec6SStephane Eranian 	if (unset)
22bcc84ec6SStephane Eranian 		return 0;
23bcc84ec6SStephane Eranian 
24bcc84ec6SStephane Eranian 	/*
25bcc84ec6SStephane Eranian 	 * cannot set it twice
26bcc84ec6SStephane Eranian 	 */
27bcc84ec6SStephane Eranian 	if (*mode)
28bcc84ec6SStephane Eranian 		return -1;
29bcc84ec6SStephane Eranian 
30af785e75SKan Liang 	if (intr)
31af785e75SKan Liang 		mask = arch__intr_reg_mask();
32af785e75SKan Liang 	else
33af785e75SKan Liang 		mask = arch__user_reg_mask();
34af785e75SKan Liang 
35bcc84ec6SStephane Eranian 	/* str may be NULL in case no arg is passed to -I */
36bcc84ec6SStephane Eranian 	if (str) {
37bcc84ec6SStephane Eranian 		/* because str is read-only */
38bcc84ec6SStephane Eranian 		s = os = strdup(str);
39bcc84ec6SStephane Eranian 		if (!s)
40bcc84ec6SStephane Eranian 			return -1;
41bcc84ec6SStephane Eranian 
42bcc84ec6SStephane Eranian 		for (;;) {
43bcc84ec6SStephane Eranian 			p = strchr(s, ',');
44bcc84ec6SStephane Eranian 			if (p)
45bcc84ec6SStephane Eranian 				*p = '\0';
46bcc84ec6SStephane Eranian 
47bcc84ec6SStephane Eranian 			if (!strcmp(s, "?")) {
48bcc84ec6SStephane Eranian 				fprintf(stderr, "available registers: ");
4942466b9fSIan Rogers #ifdef HAVE_PERF_REGS_SUPPORT
50bcc84ec6SStephane Eranian 				for (r = sample_reg_masks; r->name; r++) {
51af785e75SKan Liang 					if (r->mask & mask)
52bcc84ec6SStephane Eranian 						fprintf(stderr, "%s ", r->name);
53bcc84ec6SStephane Eranian 				}
5442466b9fSIan Rogers #endif
55bcc84ec6SStephane Eranian 				fputc('\n', stderr);
56bcc84ec6SStephane Eranian 				/* just printing available regs */
57*2eb5dd41SZheng Zengkai 				goto error;
58bcc84ec6SStephane Eranian 			}
5942466b9fSIan Rogers #ifdef HAVE_PERF_REGS_SUPPORT
60bcc84ec6SStephane Eranian 			for (r = sample_reg_masks; r->name; r++) {
61af785e75SKan Liang 				if ((r->mask & mask) && !strcasecmp(s, r->name))
62bcc84ec6SStephane Eranian 					break;
63bcc84ec6SStephane Eranian 			}
6442466b9fSIan Rogers #endif
6542466b9fSIan Rogers 			if (!r || !r->name) {
66aeea9062SKan Liang 				ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n",
67aeea9062SKan Liang 					    s, intr ? "-I" : "--user-regs=");
68bcc84ec6SStephane Eranian 				goto error;
69bcc84ec6SStephane Eranian 			}
70bcc84ec6SStephane Eranian 
71bcc84ec6SStephane Eranian 			*mode |= r->mask;
72bcc84ec6SStephane Eranian 
73bcc84ec6SStephane Eranian 			if (!p)
74bcc84ec6SStephane Eranian 				break;
75bcc84ec6SStephane Eranian 
76bcc84ec6SStephane Eranian 			s = p + 1;
77bcc84ec6SStephane Eranian 		}
78bcc84ec6SStephane Eranian 	}
79bcc84ec6SStephane Eranian 	ret = 0;
80bcc84ec6SStephane Eranian 
81bcc84ec6SStephane Eranian 	/* default to all possible regs */
82bcc84ec6SStephane Eranian 	if (*mode == 0)
83af785e75SKan Liang 		*mode = mask;
84bcc84ec6SStephane Eranian error:
85bcc84ec6SStephane Eranian 	free(os);
86bcc84ec6SStephane Eranian 	return ret;
87bcc84ec6SStephane Eranian }
88aeea9062SKan Liang 
89aeea9062SKan Liang int
parse_user_regs(const struct option * opt,const char * str,int unset)90aeea9062SKan Liang parse_user_regs(const struct option *opt, const char *str, int unset)
91aeea9062SKan Liang {
92aeea9062SKan Liang 	return __parse_regs(opt, str, unset, false);
93aeea9062SKan Liang }
94aeea9062SKan Liang 
95aeea9062SKan Liang int
parse_intr_regs(const struct option * opt,const char * str,int unset)96aeea9062SKan Liang parse_intr_regs(const struct option *opt, const char *str, int unset)
97aeea9062SKan Liang {
98aeea9062SKan Liang 	return __parse_regs(opt, str, unset, true);
99aeea9062SKan Liang }
100