1 /* LoongArch opcode support.
2 Copyright (C) 2021-2024 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/>. */
22 #include "opcode/loongarch.h"
25 is_unsigned (const char *c_str
)
27 if (c_str
[0] == '0' && (c_str
[1] == 'x' || c_str
[1] == 'X'))
30 while (('a' <= *c_str
&& *c_str
<= 'f')
31 || ('A' <= *c_str
&& *c_str
<= 'F')
32 || ('0' <= *c_str
&& *c_str
<= '9'))
35 else if (*c_str
== '\0')
38 while ('0' <= *c_str
&& *c_str
<= '9')
40 return *c_str
== '\0';
44 is_signed (const char *c_str
)
46 return *c_str
== '-' ? is_unsigned (c_str
+ 1) : is_unsigned (c_str
);
50 loongarch_get_bit_field_width (const char *bit_field
, char **end
)
53 char has_specify
= 0, *bit_field_1
= (char *) bit_field
;
54 if (bit_field_1
&& *bit_field_1
!= '\0')
57 strtol (bit_field_1
, &bit_field_1
, 10);
59 if (*bit_field_1
!= ':')
63 width
+= strtol (bit_field_1
, &bit_field_1
, 10);
66 if (*bit_field_1
!= '|')
72 return has_specify
? width
: -1;
76 loongarch_decode_imm (const char *bit_field
, insn_t insn
, int si
)
80 int len
= 0, width
, b_start
;
81 char *bit_field_1
= (char *) bit_field
;
84 b_start
= strtol (bit_field_1
, &bit_field_1
, 10);
85 if (*bit_field_1
!= ':')
87 width
= strtol (bit_field_1
+ 1, &bit_field_1
, 10);
91 t
<<= sizeof (t
) * 8 - width
- b_start
;
92 t
>>= sizeof (t
) * 8 - width
;
96 if (*bit_field_1
!= '|')
101 if (*bit_field_1
== '<' && *(++bit_field_1
) == '<')
103 width
= atoi (bit_field_1
+ 1);
107 else if (*bit_field_1
== '+')
108 ret
+= atoi (bit_field_1
+ 1);
110 /* Extend signed bit. */
113 uint32_t sign
= 1u << (len
- 1);
114 ret
= (ret
^ sign
) - sign
;
121 loongarch_encode_imm (const char *bit_field
, int32_t imm
)
123 char *bit_field_1
= (char *) bit_field
;
124 char *t
= bit_field_1
;
128 uint32_t uimm
= (uint32_t)imm
;
130 width
= loongarch_get_bit_field_width (t
, &t
);
134 if (*t
== '<' && *(++t
) == '<')
135 width
+= atoi (t
+ 1);
137 uimm
-= atoi (t
+ 1);
139 uimm
= width
? (uimm
<< (sizeof (uimm
) * 8 - width
)) : 0;
143 b_start
= strtol (bit_field_1
, &bit_field_1
, 10);
144 if (*bit_field_1
!= ':')
146 width
= strtol (bit_field_1
+ 1, &bit_field_1
, 10);
148 i
= width
? (i
>> (sizeof (i
) * 8 - width
)) : 0;
149 i
= (b_start
== 32) ? 0 : (i
<< b_start
);
151 uimm
= (width
== 32) ? 0 : (uimm
<< width
);
153 if (*bit_field_1
!= '|')
163 "v0:5,r5:5,s10:10<<2"
164 "r0:5,r5:5,r10:5,u15:2+1"
168 loongarch_parse_format (const char *format
, char *esc1s
, char *esc2s
,
169 const char **bit_fields
)
179 for "[a-zA-Z][a-zA-Z]?" */
180 if (('a' <= *format
&& *format
<= 'z')
181 || ('A' <= *format
&& *format
<= 'Z'))
183 *esc1s
++ = *format
++;
184 if (('a' <= *format
&& *format
<= 'z')
185 || ('A' <= *format
&& *format
<= 'Z'))
186 *esc2s
++ = *format
++;
194 if (MAX_ARG_NUM_PLUS_2
- 2 < arg_num
)
195 /* Need larger MAX_ARG_NUM_PLUS_2. */
198 *bit_fields
++ = format
;
200 if ('0' <= *format
&& *format
<= '9')
202 /* For "[0-9]+:[0-9]+(\|[0-9]+:[0-9]+)*". */
205 while ('0' <= *format
&& *format
<= '9')
212 if (!('0' <= *format
&& *format
<= '9'))
214 while ('0' <= *format
&& *format
<= '9')
222 /* For "((\+|<<)[1-9][0-9]*)?". */
227 else if (format
[0] == '<' && format
[1] == '<')
232 if (!('1' <= *format
&& *format
<= '9'))
234 while ('0' <= *format
&& *format
<= '9')
242 else if (*format
== '\0')
254 loongarch_split_args_by_comma (char *args
, const char *arg_strs
[])
260 bool inquote
= false;
261 arg_strs
[num
++] = args
;
262 for (; *args
; args
++)
265 else if (*args
== ',' && !inquote
)
267 if (MAX_ARG_NUM_PLUS_2
- 1 == num
)
270 arg_strs
[num
++] = args
+ 1;
273 if (*(args
- 1) == '"' && *arg_strs
[num
- 1] == '"')
276 arg_strs
[num
- 1] += 1;
280 arg_strs
[num
] = NULL
;
285 loongarch_cat_splited_strs (const char *arg_strs
[])
290 for (l
= 0, n
= 0; arg_strs
[n
]; n
++)
291 l
+= strlen (arg_strs
[n
]);
292 ret
= malloc (l
+ n
+ 1);
298 strcat (ret
, arg_strs
[0]);
299 for (l
= 1; l
< n
; l
++)
300 strcat (ret
, ","), strcat (ret
, arg_strs
[l
]);
305 loongarch_foreach_args (const char *format
, const char *arg_strs
[],
306 int32_t (*helper
) (char esc1
, char esc2
,
307 const char *bit_field
,
308 const char *arg
, void *context
),
311 char esc1s
[MAX_ARG_NUM_PLUS_2
- 1], esc2s
[MAX_ARG_NUM_PLUS_2
- 1];
312 const char *bit_fields
[MAX_ARG_NUM_PLUS_2
- 1];
317 ok
= loongarch_parse_format (format
, esc1s
, esc2s
, bit_fields
) == 0;
319 /* Make sure the num of actual args is equal to the num of escape. */
320 for (i
= 0; esc1s
[i
] && arg_strs
[i
]; i
++)
322 ok
= ok
&& !esc1s
[i
] && !arg_strs
[i
];
326 for (i
= 0; arg_strs
[i
]; i
++)
327 ret
|= loongarch_encode_imm (bit_fields
[i
],
328 helper (esc1s
[i
], esc2s
[i
],
329 bit_fields
[i
], arg_strs
[i
],
331 ret
|= helper ('\0', '\0', NULL
, NULL
, context
);
338 loongarch_check_format (const char *format
)
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];
346 return loongarch_parse_format (format
, esc1s
, esc2s
, bit_fields
);
350 loongarch_check_macro (const char *format
, const char *macro
)
353 char esc1s
[MAX_ARG_NUM_PLUS_2
- 1], esc2s
[MAX_ARG_NUM_PLUS_2
- 1];
354 const char *bit_fields
[MAX_ARG_NUM_PLUS_2
- 1];
356 if (!format
|| !macro
357 || loongarch_parse_format (format
, esc1s
, esc2s
, bit_fields
) != 0)
360 for (num_of_args
= 0; esc1s
[num_of_args
]; num_of_args
++)
363 for (; macro
[0]; macro
++)
367 if ('1' <= macro
[0] && macro
[0] <= '9')
369 if (num_of_args
< macro
[0] - '0')
370 /* Out of args num. */
373 else if (macro
[0] == 'f')
375 else if (macro
[0] == '%')
384 I (char esc_ch1 ATTRIBUTE_UNUSED
, char esc_ch2 ATTRIBUTE_UNUSED
,
391 loongarch_expand_macro_with_format_map (
392 const char *format
, const char *macro
, const char *const arg_strs
[],
393 const char *(*map
) (char esc1
, char esc2
, const char *arg
),
394 char *(*helper
) (const char *const arg_strs
[], void *context
), void *context
,
397 char esc1s
[MAX_ARG_NUM_PLUS_2
- 1], esc2s
[MAX_ARG_NUM_PLUS_2
- 1];
398 const char *bit_fields
[MAX_ARG_NUM_PLUS_2
- 1];
402 /* The expanded macro character length does not exceed 1000, and number of
403 label is 6 at most in the expanded macro. The len_str is the length of
405 char *buffer
=(char *) malloc(1024 + 6 * len_str
);
408 loongarch_parse_format (format
, esc1s
, esc2s
, bit_fields
);
417 if ('1' <= *src
&& *src
<= '9')
419 size_t i
= *src
- '1';
420 const char *t
= map (esc1s
[i
], esc2s
[i
], arg_strs
[i
]);
424 else if (*src
== '%')
426 else if (*src
== 'f' && helper
)
429 t
= b
= (*helper
) (arg_strs
, context
);
447 loongarch_expand_macro (const char *macro
, const char *const arg_strs
[],
448 char *(*helper
) (const char *const arg_strs
[],
450 void *context
, size_t len_str
)
452 return loongarch_expand_macro_with_format_map (NULL
, macro
, arg_strs
, I
,
453 helper
, context
, len_str
);
457 loongarch_bits_imm_needed (int64_t imm
, int si
)
464 uint64_t uimm
= (uint64_t) imm
;
465 uint64_t uimax
= UINT64_C (1) << 63;
466 for (ret
= 0; (uimm
& uimax
) != 0; uimm
<<= 1, ret
++)
471 ret
= loongarch_bits_imm_needed (imm
, 0) + 1;
476 for (ret
= 0; t
; t
>>= 1, ret
++)
483 loongarch_eliminate_adjacent_repeat_char (char *dest
, char c
)
490 while (src
[0] == c
&& src
[0] == src
[1])