Updated French translation for the opcodes directory.
[binutils-gdb.git] / opcodes / loongarch-coder.c
1 /* LoongArch opcode support.
2 Copyright (C) 2021 Free Software Foundation, Inc.
3 Contributed by Loongson Ltd.
4
5 This file is part of the GNU opcodes library.
6
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING3. If not,
19 see <http://www.gnu.org/licenses/>. */
20 #include "sysdep.h"
21 #include "opcode/loongarch.h"
22
23 int
24 is_unsigned (const char *c_str)
25 {
26 if (c_str[0] == '0' && (c_str[1] == 'x' || c_str[1] == 'X'))
27 {
28 c_str += 2;
29 while (('a' <= *c_str && *c_str <= 'f')
30 || ('A' <= *c_str && *c_str <= 'F')
31 || ('0' <= *c_str && *c_str <= '9'))
32 c_str++;
33 }
34 else if (*c_str == '\0')
35 return 0;
36 else
37 while ('0' <= *c_str && *c_str <= '9')
38 c_str++;
39 return *c_str == '\0';
40 }
41
42 int
43 is_signed (const char *c_str)
44 {
45 return *c_str == '-' ? is_unsigned (c_str + 1) : is_unsigned (c_str);
46 }
47
48 int
49 loongarch_get_bit_field_width (const char *bit_field, char **end)
50 {
51 int width = 0;
52 char has_specify = 0, *bit_field_1 = (char *) bit_field;
53 if (bit_field_1 && *bit_field_1 != '\0')
54 while (1)
55 {
56 strtol (bit_field_1, &bit_field_1, 10);
57
58 if (*bit_field_1 != ':')
59 break;
60 bit_field_1++;
61
62 width += strtol (bit_field_1, &bit_field_1, 10);
63 has_specify = 1;
64
65 if (*bit_field_1 != '|')
66 break;
67 bit_field_1++;
68 }
69 if (end)
70 *end = bit_field_1;
71 return has_specify ? width : -1;
72 }
73
74 int32_t
75 loongarch_decode_imm (const char *bit_field, insn_t insn, int si)
76 {
77 int32_t ret = 0;
78 uint32_t t;
79 int len = 0, width, b_start;
80 char *bit_field_1 = (char *) bit_field;
81 while (1)
82 {
83 b_start = strtol (bit_field_1, &bit_field_1, 10);
84 if (*bit_field_1 != ':')
85 break;
86 width = strtol (bit_field_1 + 1, &bit_field_1, 10);
87 len += width;
88
89 t = insn;
90 t <<= sizeof (t) * 8 - width - b_start;
91 t >>= sizeof (t) * 8 - width;
92 ret <<= width;
93 ret |= t;
94
95 if (*bit_field_1 != '|')
96 break;
97 bit_field_1++;
98 }
99
100 if (*bit_field_1 == '<' && *(++bit_field_1) == '<')
101 {
102 width = atoi (bit_field_1 + 1);
103 ret <<= width;
104 len += width;
105 }
106 else if (*bit_field_1 == '+')
107 ret += atoi (bit_field_1 + 1);
108
109 if (si)
110 {
111 ret <<= sizeof (ret) * 8 - len;
112 ret >>= sizeof (ret) * 8 - len;
113 }
114 return ret;
115 }
116
117 static insn_t
118 loongarch_encode_imm (const char *bit_field, int32_t imm)
119 {
120 char *bit_field_1 = (char *) bit_field;
121 char *t = bit_field_1;
122 int width, b_start;
123 insn_t ret = 0;
124 uint32_t i;
125 uint32_t uimm = (uint32_t)imm;
126
127 width = loongarch_get_bit_field_width (t, &t);
128 if (width == -1)
129 return ret;
130
131 if (*t == '<' && *(++t) == '<')
132 width += atoi (t + 1);
133 else if (*t == '+')
134 uimm -= atoi (t + 1);
135
136 uimm <<= sizeof (uimm) * 8 - width;
137 while (1)
138 {
139 b_start = strtol (bit_field_1, &bit_field_1, 10);
140 if (*bit_field_1 != ':')
141 break;
142 width = strtol (bit_field_1 + 1, &bit_field_1, 10);
143 i = uimm;
144 i >>= sizeof (i) * 8 - width;
145 i <<= b_start;
146 ret |= i;
147 uimm <<= width;
148
149 if (*bit_field_1 != '|')
150 break;
151 bit_field_1++;
152 }
153 return ret;
154 }
155
156 /* Parse such FORMAT
157 ""
158 "u"
159 "v0:5,r5:5,s10:10<<2"
160 "r0:5,r5:5,r10:5,u15:2+1"
161 "r,r,u0:5+32,u0:5+1"
162 */
163 static int
164 loongarch_parse_format (const char *format, char *esc1s, char *esc2s,
165 const char **bit_fields)
166 {
167 size_t arg_num = 0;
168
169 if (*format == '\0')
170 goto end;
171
172 while (1)
173 {
174 /* esc1 esc2
175 for "[a-zA-Z][a-zA-Z]?" */
176 if (('a' <= *format && *format <= 'z')
177 || ('A' <= *format && *format <= 'Z'))
178 {
179 *esc1s++ = *format++;
180 if (('a' <= *format && *format <= 'z')
181 || ('A' <= *format && *format <= 'Z'))
182 *esc2s++ = *format++;
183 else
184 *esc2s++ = '\0';
185 }
186 else
187 return -1;
188
189 arg_num++;
190 if (MAX_ARG_NUM_PLUS_2 - 2 < arg_num)
191 /* Need larger MAX_ARG_NUM_PLUS_2. */
192 return -1;
193
194 *bit_fields++ = format;
195
196 if ('0' <= *format && *format <= '9')
197 {
198 /* For "[0-9]+:[0-9]+(\|[0-9]+:[0-9]+)*". */
199 while (1)
200 {
201 while ('0' <= *format && *format <= '9')
202 format++;
203
204 if (*format != ':')
205 return -1;
206 format++;
207
208 if (!('0' <= *format && *format <= '9'))
209 return -1;
210 while ('0' <= *format && *format <= '9')
211 format++;
212
213 if (*format != '|')
214 break;
215 format++;
216 }
217
218 /* For "((\+|<<)[1-9][0-9]*)?". */
219 do
220 {
221 if (*format == '+')
222 format++;
223 else if (format[0] == '<' && format[1] == '<')
224 format += 2;
225 else
226 break;
227
228 if (!('1' <= *format && *format <= '9'))
229 return -1;
230 while ('0' <= *format && *format <= '9')
231 format++;
232 }
233 while (0);
234 }
235
236 if (*format == ',')
237 format++;
238 else if (*format == '\0')
239 break;
240 else
241 return -1;
242 }
243
244 end:
245 *esc1s = '\0';
246 return 0;
247 }
248
249 size_t
250 loongarch_split_args_by_comma (char *args, const char *arg_strs[])
251 {
252 size_t num = 0;
253
254 if (*args)
255 arg_strs[num++] = args;
256 for (; *args; args++)
257 if (*args == ',')
258 {
259 if (MAX_ARG_NUM_PLUS_2 - 1 == num)
260 break;
261 else
262 *args = '\0', arg_strs[num++] = args + 1;
263 }
264 arg_strs[num] = NULL;
265 return num;
266 }
267
268 char *
269 loongarch_cat_splited_strs (const char *arg_strs[])
270 {
271 char *ret;
272 size_t n, l;
273
274 for (l = 0, n = 0; arg_strs[n]; n++)
275 l += strlen (arg_strs[n]);
276 ret = malloc (l + n + 1);
277 if (!ret)
278 return ret;
279
280 ret[0] = '\0';
281 if (0 < n)
282 strcat (ret, arg_strs[0]);
283 for (l = 1; l < n; l++)
284 strcat (ret, ","), strcat (ret, arg_strs[l]);
285 return ret;
286 }
287
288 insn_t
289 loongarch_foreach_args (const char *format, const char *arg_strs[],
290 int32_t (*helper) (char esc1, char esc2,
291 const char *bit_field,
292 const char *arg, void *context),
293 void *context)
294 {
295 char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
296 const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
297 size_t i;
298 insn_t ret = 0;
299 int ok;
300
301 ok = loongarch_parse_format (format, esc1s, esc2s, bit_fields) == 0;
302
303 /* Make sure the num of actual args is equal to the num of escape. */
304 for (i = 0; esc1s[i] && arg_strs[i]; i++)
305 ;
306 ok = ok && !esc1s[i] && !arg_strs[i];
307
308 if (ok && helper)
309 {
310 for (i = 0; arg_strs[i]; i++)
311 ret |= loongarch_encode_imm (bit_fields[i],
312 helper (esc1s[i], esc2s[i],
313 bit_fields[i], arg_strs[i],
314 context));
315 ret |= helper ('\0', '\0', NULL, NULL, context);
316 }
317
318 return ret;
319 }
320
321 int
322 loongarch_check_format (const char *format)
323 {
324 char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
325 const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
326
327 if (!format)
328 return -1;
329
330 return loongarch_parse_format (format, esc1s, esc2s, bit_fields);
331 }
332
333 int
334 loongarch_check_macro (const char *format, const char *macro)
335 {
336 int num_of_args;
337 char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
338 const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
339
340 if (!format || !macro
341 || loongarch_parse_format (format, esc1s, esc2s, bit_fields) != 0)
342 return -1;
343
344 for (num_of_args = 0; esc1s[num_of_args]; num_of_args++)
345 ;
346
347 for (; macro[0]; macro++)
348 if (macro[0] == '%')
349 {
350 macro++;
351 if ('1' <= macro[0] && macro[0] <= '9')
352 {
353 if (num_of_args < macro[0] - '0')
354 /* Out of args num. */
355 return -1;
356 }
357 else if (macro[0] == 'f')
358 ;
359 else if (macro[0] == '%')
360 ;
361 else
362 return -1;
363 }
364 return 0;
365 }
366
367 static const char *
368 I (char esc_ch1 ATTRIBUTE_UNUSED, char esc_ch2 ATTRIBUTE_UNUSED,
369 const char *c_str)
370 {
371 return c_str;
372 }
373
374 char *
375 loongarch_expand_macro_with_format_map (
376 const char *format, const char *macro, const char *const arg_strs[],
377 const char *(*map) (char esc1, char esc2, const char *arg),
378 char *(*helper) (const char *const arg_strs[], void *context), void *context)
379 {
380 char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
381 const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
382 const char *src;
383 char *dest;
384 char buffer[8192];
385
386 if (format)
387 loongarch_parse_format (format, esc1s, esc2s, bit_fields);
388
389 src = macro;
390 dest = buffer;
391
392 while (*src)
393 if (*src == '%')
394 {
395 src++;
396 if ('1' <= *src && *src <= '9')
397 {
398 size_t i = *src - '1';
399 const char *t = map (esc1s[i], esc2s[i], arg_strs[i]);
400 while (*t)
401 *dest++ = *t++;
402 }
403 else if (*src == '%')
404 *dest++ = '%';
405 else if (*src == 'f' && helper)
406 {
407 char *b, *t;
408 t = b = (*helper) (arg_strs, context);
409 if (b)
410 {
411 while (*t)
412 *dest++ = *t++;
413 free (b);
414 }
415 }
416 src++;
417 }
418 else
419 *dest++ = *src++;
420
421 *dest = '\0';
422 return strdup (buffer);
423 }
424
425 char *
426 loongarch_expand_macro (const char *macro, const char *const arg_strs[],
427 char *(*helper) (const char *const arg_strs[],
428 void *context),
429 void *context)
430 {
431 return loongarch_expand_macro_with_format_map (NULL, macro, arg_strs, I,
432 helper, context);
433 }
434
435 size_t
436 loongarch_bits_imm_needed (int64_t imm, int si)
437 {
438 size_t ret;
439 if (si)
440 {
441 if (imm < 0)
442 {
443 uint64_t uimm = (uint64_t) imm;
444 uint64_t uimax = UINT64_C (1) << 63;
445 for (ret = 0; (uimm & uimax) != 0; uimm <<= 1, ret++)
446 ;
447 ret = 64 - ret + 1;
448 }
449 else
450 ret = loongarch_bits_imm_needed (imm, 0) + 1;
451 }
452 else
453 {
454 uint64_t t = imm;
455 for (ret = 0; t; t >>= 1, ret++)
456 ;
457 }
458 return ret;
459 }
460
461 void
462 loongarch_eliminate_adjacent_repeat_char (char *dest, char c)
463 {
464 if (c == '\0')
465 return;
466 char *src = dest;
467 while (*dest)
468 {
469 while (src[0] == c && src[0] == src[1])
470 src++;
471 *dest++ = *src++;
472 }
473 }