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
is_branch_cond(const char * cond)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
is_branch_reg_cond(const char * cond)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
is_branch_float_cond(const char * cond)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
sparc__associate_instruction_ops(struct arch * arch,const char * name)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
arch__new_sparc(const struct e_machine_and_e_flags * id,const char * cpuid __maybe_unused)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