xref: /linux/tools/perf/util/annotate-arch/annotate-sparc.c (revision 07b972ff09f45cfb7acd20cd9b3769c6975bc434)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <string.h>
3 #include <linux/compiler.h>
4 #include "../../util/disasm.h"
5 
6 static int is_branch_cond(const char *cond)
7 {
8 	if (cond[0] == '\0')
9 		return 1;
10 
11 	if (cond[0] == 'a' && cond[1] == '\0')
12 		return 1;
13 
14 	if (cond[0] == 'c' &&
15 	    (cond[1] == 'c' || cond[1] == 's') &&
16 	    cond[2] == '\0')
17 		return 1;
18 
19 	if (cond[0] == 'e' &&
20 	    (cond[1] == '\0' ||
21 	     (cond[1] == 'q' && cond[2] == '\0')))
22 		return 1;
23 
24 	if (cond[0] == 'g' &&
25 	    (cond[1] == '\0' ||
26 	     (cond[1] == 't' && cond[2] == '\0') ||
27 	     (cond[1] == 'e' && cond[2] == '\0') ||
28 	     (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
29 		return 1;
30 
31 	if (cond[0] == 'l' &&
32 	    (cond[1] == '\0' ||
33 	     (cond[1] == 't' && cond[2] == '\0') ||
34 	     (cond[1] == 'u' && cond[2] == '\0') ||
35 	     (cond[1] == 'e' && cond[2] == '\0') ||
36 	     (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
37 		return 1;
38 
39 	if (cond[0] == 'n' &&
40 	    (cond[1] == '\0' ||
41 	     (cond[1] == 'e' && cond[2] == '\0') ||
42 	     (cond[1] == 'z' && cond[2] == '\0') ||
43 	     (cond[1] == 'e' && cond[2] == 'g' && cond[3] == '\0')))
44 		return 1;
45 
46 	if (cond[0] == 'b' &&
47 	    cond[1] == 'p' &&
48 	    cond[2] == 'o' &&
49 	    cond[3] == 's' &&
50 	    cond[4] == '\0')
51 		return 1;
52 
53 	if (cond[0] == 'v' &&
54 	    (cond[1] == 'c' || cond[1] == 's') &&
55 	    cond[2] == '\0')
56 		return 1;
57 
58 	if (cond[0] == 'b' &&
59 	    cond[1] == 'z' &&
60 	    cond[2] == '\0')
61 		return 1;
62 
63 	return 0;
64 }
65 
66 static int is_branch_reg_cond(const char *cond)
67 {
68 	if ((cond[0] == 'n' || cond[0] == 'l') &&
69 	    cond[1] == 'z' &&
70 	    cond[2] == '\0')
71 		return 1;
72 
73 	if (cond[0] == 'z' &&
74 	    cond[1] == '\0')
75 		return 1;
76 
77 	if ((cond[0] == 'g' || cond[0] == 'l') &&
78 	    cond[1] == 'e' &&
79 	    cond[2] == 'z' &&
80 	    cond[3] == '\0')
81 		return 1;
82 
83 	if (cond[0] == 'g' &&
84 	    cond[1] == 'z' &&
85 	    cond[2] == '\0')
86 		return 1;
87 
88 	return 0;
89 }
90 
91 static int is_branch_float_cond(const char *cond)
92 {
93 	if (cond[0] == '\0')
94 		return 1;
95 
96 	if ((cond[0] == 'a' || cond[0] == 'e' ||
97 	     cond[0] == 'z' || cond[0] == 'g' ||
98 	     cond[0] == 'l' || cond[0] == 'n' ||
99 	     cond[0] == 'o' || cond[0] == 'u') &&
100 	    cond[1] == '\0')
101 		return 1;
102 
103 	if (((cond[0] == 'g' && cond[1] == 'e') ||
104 	     (cond[0] == 'l' && (cond[1] == 'e' ||
105 				 cond[1] == 'g')) ||
106 	     (cond[0] == 'n' && (cond[1] == 'e' ||
107 				 cond[1] == 'z')) ||
108 	     (cond[0] == 'u' && (cond[1] == 'e' ||
109 				 cond[1] == 'g' ||
110 				 cond[1] == 'l'))) &&
111 	    cond[2] == '\0')
112 		return 1;
113 
114 	if (cond[0] == 'u' &&
115 	    (cond[1] == 'g' || cond[1] == 'l') &&
116 	    cond[2] == 'e' &&
117 	    cond[3] == '\0')
118 		return 1;
119 
120 	return 0;
121 }
122 
123 static const struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name)
124 {
125 	const struct ins_ops *ops = NULL;
126 
127 	if (!strcmp(name, "call") ||
128 	    !strcmp(name, "jmp") ||
129 	    !strcmp(name, "jmpl")) {
130 		ops = &call_ops;
131 	} else if (!strcmp(name, "ret") ||
132 		   !strcmp(name, "retl") ||
133 		   !strcmp(name, "return")) {
134 		ops = &ret_ops;
135 	} else if (!strcmp(name, "mov")) {
136 		ops = &mov_ops;
137 	} else {
138 		if (name[0] == 'c' &&
139 		    (name[1] == 'w' || name[1] == 'x'))
140 			name += 2;
141 
142 		if (name[0] == 'b') {
143 			const char *cond = name + 1;
144 
145 			if (cond[0] == 'r') {
146 				if (is_branch_reg_cond(cond + 1))
147 					ops = &jump_ops;
148 			} else if (is_branch_cond(cond)) {
149 				ops = &jump_ops;
150 			}
151 		} else if (name[0] == 'f' && name[1] == 'b') {
152 			if (is_branch_float_cond(name + 2))
153 				ops = &jump_ops;
154 		}
155 	}
156 
157 	if (ops)
158 		arch__associate_ins_ops(arch, name, ops);
159 
160 	return ops;
161 }
162 
163 int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
164 {
165 	if (!arch->initialized) {
166 		arch->initialized = true;
167 		arch->associate_instruction_ops = sparc__associate_instruction_ops;
168 		arch->objdump.comment_char = '#';
169 	}
170 
171 	return 0;
172 }
173