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