1/* LoongArch opcode support. 2 Copyright (C) 2021-2022 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 23int 24is_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 42int 43is_signed (const char *c_str) 44{ 45 return *c_str == '-' ? is_unsigned (c_str + 1) : is_unsigned (c_str); 46} 47 48int 49loongarch_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 74int32_t 75loongarch_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 /* Extend signed bit. */ 110 if (si) 111 { 112 uint32_t sign = 1u << (len - 1); 113 ret = (ret ^ sign) - sign; 114 } 115 116 return ret; 117} 118 119static insn_t 120loongarch_encode_imm (const char *bit_field, int32_t imm) 121{ 122 char *bit_field_1 = (char *) bit_field; 123 char *t = bit_field_1; 124 int width, b_start; 125 insn_t ret = 0; 126 uint32_t i; 127 uint32_t uimm = (uint32_t)imm; 128 129 width = loongarch_get_bit_field_width (t, &t); 130 if (width == -1) 131 return ret; 132 133 if (*t == '<' && *(++t) == '<') 134 width += atoi (t + 1); 135 else if (*t == '+') 136 uimm -= atoi (t + 1); 137 138 uimm = width ? (uimm << (sizeof (uimm) * 8 - width)) : 0; 139 140 while (1) 141 { 142 b_start = strtol (bit_field_1, &bit_field_1, 10); 143 if (*bit_field_1 != ':') 144 break; 145 width = strtol (bit_field_1 + 1, &bit_field_1, 10); 146 i = uimm; 147 i = width ? (i >> (sizeof (i) * 8 - width)) : 0; 148 i = (b_start == 32) ? 0 : (i << b_start); 149 ret |= i; 150 uimm = (width == 32) ? 0 : (uimm << width); 151 152 if (*bit_field_1 != '|') 153 break; 154 bit_field_1++; 155 } 156 return ret; 157} 158 159/* Parse such FORMAT 160 "" 161 "u" 162 "v0:5,r5:5,s10:10<<2" 163 "r0:5,r5:5,r10:5,u15:2+1" 164 "r,r,u0:5+32,u0:5+1" 165*/ 166static int 167loongarch_parse_format (const char *format, char *esc1s, char *esc2s, 168 const char **bit_fields) 169{ 170 size_t arg_num = 0; 171 172 if (*format == '\0') 173 goto end; 174 175 while (1) 176 { 177 /* esc1 esc2 178 for "[a-zA-Z][a-zA-Z]?" */ 179 if (('a' <= *format && *format <= 'z') 180 || ('A' <= *format && *format <= 'Z')) 181 { 182 *esc1s++ = *format++; 183 if (('a' <= *format && *format <= 'z') 184 || ('A' <= *format && *format <= 'Z')) 185 *esc2s++ = *format++; 186 else 187 *esc2s++ = '\0'; 188 } 189 else 190 return -1; 191 192 arg_num++; 193 if (MAX_ARG_NUM_PLUS_2 - 2 < arg_num) 194 /* Need larger MAX_ARG_NUM_PLUS_2. */ 195 return -1; 196 197 *bit_fields++ = format; 198 199 if ('0' <= *format && *format <= '9') 200 { 201 /* For "[0-9]+:[0-9]+(\|[0-9]+:[0-9]+)*". */ 202 while (1) 203 { 204 while ('0' <= *format && *format <= '9') 205 format++; 206 207 if (*format != ':') 208 return -1; 209 format++; 210 211 if (!('0' <= *format && *format <= '9')) 212 return -1; 213 while ('0' <= *format && *format <= '9') 214 format++; 215 216 if (*format != '|') 217 break; 218 format++; 219 } 220 221 /* For "((\+|<<)[1-9][0-9]*)?". */ 222 do 223 { 224 if (*format == '+') 225 format++; 226 else if (format[0] == '<' && format[1] == '<') 227 format += 2; 228 else 229 break; 230 231 if (!('1' <= *format && *format <= '9')) 232 return -1; 233 while ('0' <= *format && *format <= '9') 234 format++; 235 } 236 while (0); 237 } 238 239 if (*format == ',') 240 format++; 241 else if (*format == '\0') 242 break; 243 else 244 return -1; 245 } 246 247 end: 248 *esc1s = '\0'; 249 return 0; 250} 251 252size_t 253loongarch_split_args_by_comma (char *args, const char *arg_strs[]) 254{ 255 size_t num = 0; 256 257 if (*args) 258 arg_strs[num++] = args; 259 for (; *args; args++) 260 if (*args == ',') 261 { 262 if (MAX_ARG_NUM_PLUS_2 - 1 == num) 263 break; 264 else 265 *args = '\0', arg_strs[num++] = args + 1; 266 } 267 arg_strs[num] = NULL; 268 return num; 269} 270 271char * 272loongarch_cat_splited_strs (const char *arg_strs[]) 273{ 274 char *ret; 275 size_t n, l; 276 277 for (l = 0, n = 0; arg_strs[n]; n++) 278 l += strlen (arg_strs[n]); 279 ret = malloc (l + n + 1); 280 if (!ret) 281 return ret; 282 283 ret[0] = '\0'; 284 if (0 < n) 285 strcat (ret, arg_strs[0]); 286 for (l = 1; l < n; l++) 287 strcat (ret, ","), strcat (ret, arg_strs[l]); 288 return ret; 289} 290 291insn_t 292loongarch_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), 296 void *context) 297{ 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]; 300 size_t i; 301 insn_t ret = 0; 302 int ok; 303 304 ok = loongarch_parse_format (format, esc1s, esc2s, bit_fields) == 0; 305 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++) 308 ; 309 ok = ok && !esc1s[i] && !arg_strs[i]; 310 311 if (ok && helper) 312 { 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], 317 context)); 318 ret |= helper ('\0', '\0', NULL, NULL, context); 319 } 320 321 return ret; 322} 323 324int 325loongarch_check_format (const char *format) 326{ 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]; 329 330 if (!format) 331 return -1; 332 333 return loongarch_parse_format (format, esc1s, esc2s, bit_fields); 334} 335 336int 337loongarch_check_macro (const char *format, const char *macro) 338{ 339 int num_of_args; 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]; 342 343 if (!format || !macro 344 || loongarch_parse_format (format, esc1s, esc2s, bit_fields) != 0) 345 return -1; 346 347 for (num_of_args = 0; esc1s[num_of_args]; num_of_args++) 348 ; 349 350 for (; macro[0]; macro++) 351 if (macro[0] == '%') 352 { 353 macro++; 354 if ('1' <= macro[0] && macro[0] <= '9') 355 { 356 if (num_of_args < macro[0] - '0') 357 /* Out of args num. */ 358 return -1; 359 } 360 else if (macro[0] == 'f') 361 ; 362 else if (macro[0] == '%') 363 ; 364 else 365 return -1; 366 } 367 return 0; 368} 369 370static const char * 371I (char esc_ch1 ATTRIBUTE_UNUSED, char esc_ch2 ATTRIBUTE_UNUSED, 372 const char *c_str) 373{ 374 return c_str; 375} 376 377char * 378loongarch_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, 382 size_t len_str) 383{ 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]; 386 const char *src; 387 char *dest; 388 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 391 str. */ 392 char *buffer =(char *) malloc(1024 + 6 * len_str); 393 394 if (format) 395 loongarch_parse_format (format, esc1s, esc2s, bit_fields); 396 397 src = macro; 398 dest = buffer; 399 400 while (*src) 401 if (*src == '%') 402 { 403 src++; 404 if ('1' <= *src && *src <= '9') 405 { 406 size_t i = *src - '1'; 407 const char *t = map (esc1s[i], esc2s[i], arg_strs[i]); 408 while (*t) 409 *dest++ = *t++; 410 } 411 else if (*src == '%') 412 *dest++ = '%'; 413 else if (*src == 'f' && helper) 414 { 415 char *b, *t; 416 t = b = (*helper) (arg_strs, context); 417 if (b) 418 { 419 while (*t) 420 *dest++ = *t++; 421 free (b); 422 } 423 } 424 src++; 425 } 426 else 427 *dest++ = *src++; 428 429 *dest = '\0'; 430 return buffer; 431} 432 433char * 434loongarch_expand_macro (const char *macro, const char *const arg_strs[], 435 char *(*helper) (const char *const arg_strs[], 436 void *context), 437 void *context, size_t len_str) 438{ 439 return loongarch_expand_macro_with_format_map (NULL, macro, arg_strs, I, 440 helper, context, len_str); 441} 442 443size_t 444loongarch_bits_imm_needed (int64_t imm, int si) 445{ 446 size_t ret; 447 if (si) 448 { 449 if (imm < 0) 450 { 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++) 454 ; 455 ret = 64 - ret + 1; 456 } 457 else 458 ret = loongarch_bits_imm_needed (imm, 0) + 1; 459 } 460 else 461 { 462 uint64_t t = imm; 463 for (ret = 0; t; t >>= 1, ret++) 464 ; 465 } 466 return ret; 467} 468 469void 470loongarch_eliminate_adjacent_repeat_char (char *dest, char c) 471{ 472 if (c == '\0') 473 return; 474 char *src = dest; 475 while (*dest) 476 { 477 while (src[0] == c && src[0] == src[1]) 478 src++; 479 *dest++ = *src++; 480 } 481} 482