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 }
170