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