1 /* LoongArch opcode support.
2 Copyright (C) 2021-2022 Free Software Foundation, Inc.
3 Contributed by Loongson Ltd.
5 This file is part of the GNU opcodes library.
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)
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.
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/>. */
21 #include "opcode/loongarch.h"
24 is_unsigned (const char *c_str)
26 if (c_str[0] == '0' && (c_str[1] == 'x' || c_str[1] == 'X'))
29 while (('a' <= *c_str && *c_str <= 'f')
30 || ('A' <= *c_str && *c_str <= 'F')
31 || ('0' <= *c_str && *c_str <= '9'))
34 else if (*c_str == '\0')
37 while ('0' <= *c_str && *c_str <= '9')
39 return *c_str == '\0';
43 is_signed (const char *c_str)
45 return *c_str == '-' ? is_unsigned (c_str + 1) : is_unsigned (c_str);
49 loongarch_get_bit_field_width (const char *bit_field, char **end)
52 char has_specify = 0, *bit_field_1 = (char *) bit_field;
53 if (bit_field_1 && *bit_field_1 != '\0')
56 strtol (bit_field_1, &bit_field_1, 10);
58 if (*bit_field_1 != ':')
62 width += strtol (bit_field_1, &bit_field_1, 10);
65 if (*bit_field_1 != '|')
71 return has_specify ? width : -1;
75 loongarch_decode_imm (const char *bit_field, insn_t insn, int si)
79 int len = 0, width, b_start;
80 char *bit_field_1 = (char *) bit_field;
83 b_start = strtol (bit_field_1, &bit_field_1, 10);
84 if (*bit_field_1 != ':')
86 width = strtol (bit_field_1 + 1, &bit_field_1, 10);
90 t <<= sizeof (t) * 8 - width - b_start;
91 t >>= sizeof (t) * 8 - width;
95 if (*bit_field_1 != '|')
100 if (*bit_field_1 == '<' && *(++bit_field_1) == '<')
102 width = atoi (bit_field_1 + 1);
106 else if (*bit_field_1 == '+')
107 ret += atoi (bit_field_1 + 1);
109 /* Extend signed bit. */
112 uint32_t sign = 1u << (len - 1);
113 ret = (ret ^ sign) - sign;
120 loongarch_encode_imm (const char *bit_field, int32_t imm)
122 char *bit_field_1 = (char *) bit_field;
123 char *t = bit_field_1;
127 uint32_t uimm = (uint32_t)imm;
129 width = loongarch_get_bit_field_width (t, &t);
133 if (*t == '<' && *(++t) == '<')
134 width += atoi (t + 1);
136 uimm -= atoi (t + 1);
138 uimm = width ? (uimm << (sizeof (uimm) * 8 - width)) : 0;
142 b_start = strtol (bit_field_1, &bit_field_1, 10);
143 if (*bit_field_1 != ':')
145 width = strtol (bit_field_1 + 1, &bit_field_1, 10);
147 i = width ? (i >> (sizeof (i) * 8 - width)) : 0;
148 i = (b_start == 32) ? 0 : (i << b_start);
150 uimm = (width == 32) ? 0 : (uimm << width);
152 if (*bit_field_1 != '|')
162 "v0:5,r5:5,s10:10<<2"
163 "r0:5,r5:5,r10:5,u15:2+1"
167 loongarch_parse_format (const char *format, char *esc1s, char *esc2s,
168 const char **bit_fields)
178 for "[a-zA-Z][a-zA-Z]?" */
179 if (('a' <= *format && *format <= 'z')
180 || ('A' <= *format && *format <= 'Z'))
182 *esc1s++ = *format++;
183 if (('a' <= *format && *format <= 'z')
184 || ('A' <= *format && *format <= 'Z'))
185 *esc2s++ = *format++;
193 if (MAX_ARG_NUM_PLUS_2 - 2 < arg_num)
194 /* Need larger MAX_ARG_NUM_PLUS_2. */
197 *bit_fields++ = format;
199 if ('0' <= *format && *format <= '9')
201 /* For "[0-9]+:[0-9]+(\|[0-9]+:[0-9]+)*". */
204 while ('0' <= *format && *format <= '9')
211 if (!('0' <= *format && *format <= '9'))
213 while ('0' <= *format && *format <= '9')
221 /* For "((\+|<<)[1-9][0-9]*)?". */
226 else if (format[0] == '<' && format[1] == '<')
231 if (!('1' <= *format && *format <= '9'))
233 while ('0' <= *format && *format <= '9')
241 else if (*format == '\0')
253 loongarch_split_args_by_comma (char *args, const char *arg_strs[])
258 arg_strs[num++] = args;
259 for (; *args; args++)
262 if (MAX_ARG_NUM_PLUS_2 - 1 == num)
265 *args = '\0', arg_strs[num++] = args + 1;
267 arg_strs[num] = NULL;
272 loongarch_cat_splited_strs (const char *arg_strs[])
277 for (l = 0, n = 0; arg_strs[n]; n++)
278 l += strlen (arg_strs[n]);
279 ret = malloc (l + n + 1);
285 strcat (ret, arg_strs[0]);
286 for (l = 1; l < n; l++)
287 strcat (ret, ","), strcat (ret, arg_strs[l]);
292 loongarch_foreach_args (const char *format, const char *arg_strs[],
293 int32_t (*helper) (char esc1, char esc2,
294 const char *bit_field,
295 const char *arg, void *context),
298 char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
299 const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
304 ok = loongarch_parse_format (format, esc1s, esc2s, bit_fields) == 0;
306 /* Make sure the num of actual args is equal to the num of escape. */
307 for (i = 0; esc1s[i] && arg_strs[i]; i++)
309 ok = ok && !esc1s[i] && !arg_strs[i];
313 for (i = 0; arg_strs[i]; i++)
314 ret |= loongarch_encode_imm (bit_fields[i],
315 helper (esc1s[i], esc2s[i],
316 bit_fields[i], arg_strs[i],
318 ret |= helper ('\0', '\0', NULL, NULL, context);
325 loongarch_check_format (const char *format)
327 char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
328 const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
333 return loongarch_parse_format (format, esc1s, esc2s, bit_fields);
337 loongarch_check_macro (const char *format, const char *macro)
340 char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
341 const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
343 if (!format || !macro
344 || loongarch_parse_format (format, esc1s, esc2s, bit_fields) != 0)
347 for (num_of_args = 0; esc1s[num_of_args]; num_of_args++)
350 for (; macro[0]; macro++)
354 if ('1' <= macro[0] && macro[0] <= '9')
356 if (num_of_args < macro[0] - '0')
357 /* Out of args num. */
360 else if (macro[0] == 'f')
362 else if (macro[0] == '%')
371 I (char esc_ch1 ATTRIBUTE_UNUSED, char esc_ch2 ATTRIBUTE_UNUSED,
378 loongarch_expand_macro_with_format_map (
379 const char *format, const char *macro, const char *const arg_strs[],
380 const char *(*map) (char esc1, char esc2, const char *arg),
381 char *(*helper) (const char *const arg_strs[], void *context), void *context,
384 char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
385 const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
389 /* The expanded macro character length does not exceed 1000, and number of
390 label is 6 at most in the expanded macro. The len_str is the length of
392 char *buffer =(char *) malloc(1024 + 6 * len_str);
395 loongarch_parse_format (format, esc1s, esc2s, bit_fields);
404 if ('1' <= *src && *src <= '9')
406 size_t i = *src - '1';
407 const char *t = map (esc1s[i], esc2s[i], arg_strs[i]);
411 else if (*src == '%')
413 else if (*src == 'f' && helper)
416 t = b = (*helper) (arg_strs, context);
434 loongarch_expand_macro (const char *macro, const char *const arg_strs[],
435 char *(*helper) (const char *const arg_strs[],
437 void *context, size_t len_str)
439 return loongarch_expand_macro_with_format_map (NULL, macro, arg_strs, I,
440 helper, context, len_str);
444 loongarch_bits_imm_needed (int64_t imm, int si)
451 uint64_t uimm = (uint64_t) imm;
452 uint64_t uimax = UINT64_C (1) << 63;
453 for (ret = 0; (uimm & uimax) != 0; uimm <<= 1, ret++)
458 ret = loongarch_bits_imm_needed (imm, 0) + 1;
463 for (ret = 0; t; t >>= 1, ret++)
470 loongarch_eliminate_adjacent_repeat_char (char *dest, char c)
477 while (src[0] == c && src[0] == src[1])