Coverage Report

Created: 2023-08-28 06:31

/src/binutils-gdb/opcodes/loongarch-coder.c
Line
Count
Source (jump to first uncovered line)
1
/* LoongArch opcode support.
2
   Copyright (C) 2021-2023 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
0
{
26
0
  if (c_str[0] == '0' && (c_str[1] == 'x' || c_str[1] == 'X'))
27
0
    {
28
0
      c_str += 2;
29
0
      while (('a' <= *c_str && *c_str <= 'f')
30
0
       || ('A' <= *c_str && *c_str <= 'F')
31
0
       || ('0' <= *c_str && *c_str <= '9'))
32
0
  c_str++;
33
0
    }
34
0
  else if (*c_str == '\0')
35
0
    return 0;
36
0
  else
37
0
    while ('0' <= *c_str && *c_str <= '9')
38
0
      c_str++;
39
0
  return *c_str == '\0';
40
0
}
41
42
int
43
is_signed (const char *c_str)
44
0
{
45
0
  return *c_str == '-' ? is_unsigned (c_str + 1) : is_unsigned (c_str);
46
0
}
47
48
int
49
loongarch_get_bit_field_width (const char *bit_field, char **end)
50
66.0k
{
51
66.0k
  int width = 0;
52
66.0k
  char has_specify = 0, *bit_field_1 = (char *) bit_field;
53
66.0k
  if (bit_field_1 && *bit_field_1 != '\0')
54
68.4k
    while (1)
55
68.4k
      {
56
68.4k
  strtol (bit_field_1, &bit_field_1, 10);
57
58
68.4k
  if (*bit_field_1 != ':')
59
0
    break;
60
68.4k
  bit_field_1++;
61
62
68.4k
  width += strtol (bit_field_1, &bit_field_1, 10);
63
68.4k
  has_specify = 1;
64
65
68.4k
  if (*bit_field_1 != '|')
66
66.0k
    break;
67
2.40k
  bit_field_1++;
68
2.40k
      }
69
66.0k
  if (end)
70
66.0k
    *end = bit_field_1;
71
66.0k
  return has_specify ? width : -1;
72
66.0k
}
73
74
int32_t
75
loongarch_decode_imm (const char *bit_field, insn_t insn, int si)
76
132k
{
77
132k
  int32_t ret = 0;
78
132k
  uint32_t t;
79
132k
  int len = 0, width, b_start;
80
132k
  char *bit_field_1 = (char *) bit_field;
81
136k
  while (1)
82
136k
    {
83
136k
      b_start = strtol (bit_field_1, &bit_field_1, 10);
84
136k
      if (*bit_field_1 != ':')
85
0
  break;
86
136k
      width = strtol (bit_field_1 + 1, &bit_field_1, 10);
87
136k
      len += width;
88
89
136k
      t = insn;
90
136k
      t <<= sizeof (t) * 8 - width - b_start;
91
136k
      t >>= sizeof (t) * 8 - width;
92
136k
      ret <<= width;
93
136k
      ret |= t;
94
95
136k
      if (*bit_field_1 != '|')
96
132k
  break;
97
4.80k
      bit_field_1++;
98
4.80k
    }
99
100
132k
  if (*bit_field_1 == '<' && *(++bit_field_1) == '<')
101
20.8k
    {
102
20.8k
      width = atoi (bit_field_1 + 1);
103
20.8k
      ret <<= width;
104
20.8k
      len += width;
105
20.8k
    }
106
111k
  else if (*bit_field_1 == '+')
107
942
    ret += atoi (bit_field_1 + 1);
108
109
  /* Extend signed bit.  */
110
132k
  if (si)
111
66.0k
    {
112
66.0k
      uint32_t sign = 1u << (len - 1);
113
66.0k
      ret = (ret ^ sign) - sign;
114
66.0k
    }
115
116
132k
  return ret;
117
132k
}
118
119
static insn_t
120
loongarch_encode_imm (const char *bit_field, int32_t imm)
121
66.0k
{
122
66.0k
  char *bit_field_1 = (char *) bit_field;
123
66.0k
  char *t = bit_field_1;
124
66.0k
  int width, b_start;
125
66.0k
  insn_t ret = 0;
126
66.0k
  uint32_t i;
127
66.0k
  uint32_t uimm = (uint32_t)imm;
128
129
66.0k
  width = loongarch_get_bit_field_width (t, &t);
130
66.0k
  if (width == -1)
131
0
    return ret;
132
133
66.0k
  if (*t == '<' && *(++t) == '<')
134
10.4k
    width += atoi (t + 1);
135
55.6k
  else if (*t == '+')
136
471
    uimm -= atoi (t + 1);
137
138
66.0k
  uimm = width ? (uimm << (sizeof (uimm) * 8 - width)) : 0;
139
140
68.4k
  while (1)
141
68.4k
    {
142
68.4k
      b_start = strtol (bit_field_1, &bit_field_1, 10);
143
68.4k
      if (*bit_field_1 != ':')
144
0
  break;
145
68.4k
      width = strtol (bit_field_1 + 1, &bit_field_1, 10);
146
68.4k
      i = uimm;
147
68.4k
      i = width ? (i >> (sizeof (i) * 8 - width)) : 0;
148
68.4k
      i = (b_start == 32) ? 0 : (i << b_start);
149
68.4k
      ret |= i;
150
68.4k
      uimm = (width == 32) ? 0 : (uimm << width);
151
152
68.4k
      if (*bit_field_1 != '|')
153
66.0k
  break;
154
2.40k
      bit_field_1++;
155
2.40k
    }
156
66.0k
  return ret;
157
66.0k
}
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
*/
166
static int
167
loongarch_parse_format (const char *format, char *esc1s, char *esc2s,
168
      const char **bit_fields)
169
23.8k
{
170
23.8k
  size_t arg_num = 0;
171
172
23.8k
  if (*format == '\0')
173
3
    goto end;
174
175
66.0k
  while (1)
176
66.0k
    {
177
      /* esc1    esc2
178
   for "[a-zA-Z][a-zA-Z]?"  */
179
66.0k
      if (('a' <= *format && *format <= 'z')
180
66.0k
    || ('A' <= *format && *format <= 'Z'))
181
66.0k
  {
182
66.0k
    *esc1s++ = *format++;
183
66.0k
    if (('a' <= *format && *format <= 'z')
184
66.0k
        || ('A' <= *format && *format <= 'Z'))
185
12.1k
      *esc2s++ = *format++;
186
53.9k
    else
187
53.9k
      *esc2s++ = '\0';
188
66.0k
  }
189
0
      else
190
0
  return -1;
191
192
66.0k
      arg_num++;
193
66.0k
      if (MAX_ARG_NUM_PLUS_2 - 2 < arg_num)
194
  /* Need larger MAX_ARG_NUM_PLUS_2.  */
195
0
  return -1;
196
197
66.0k
      *bit_fields++ = format;
198
199
66.0k
      if ('0' <= *format && *format <= '9')
200
66.0k
  {
201
    /* For "[0-9]+:[0-9]+(\|[0-9]+:[0-9]+)*".  */
202
68.4k
    while (1)
203
68.4k
      {
204
159k
        while ('0' <= *format && *format <= '9')
205
91.1k
    format++;
206
207
68.4k
        if (*format != ':')
208
0
    return -1;
209
68.4k
        format++;
210
211
68.4k
        if (!('0' <= *format && *format <= '9'))
212
0
    return -1;
213
154k
        while ('0' <= *format && *format <= '9')
214
86.3k
    format++;
215
216
68.4k
        if (*format != '|')
217
66.0k
    break;
218
2.40k
        format++;
219
2.40k
      }
220
221
    /* For "((\+|<<)[1-9][0-9]*)?".  */
222
66.0k
    do
223
66.0k
      {
224
66.0k
        if (*format == '+')
225
471
    format++;
226
65.6k
        else if (format[0] == '<' && format[1] == '<')
227
10.4k
    format += 2;
228
55.1k
        else
229
55.1k
    break;
230
231
10.9k
        if (!('1' <= *format && *format <= '9'))
232
0
    return -1;
233
21.8k
        while ('0' <= *format && *format <= '9')
234
10.9k
    format++;
235
10.9k
      }
236
66.0k
    while (0);
237
66.0k
  }
238
239
66.0k
      if (*format == ',')
240
42.1k
  format++;
241
23.8k
      else if (*format == '\0')
242
23.8k
  break;
243
0
      else
244
0
  return -1;
245
66.0k
    }
246
247
23.8k
 end:
248
23.8k
  *esc1s = '\0';
249
23.8k
  return 0;
250
23.8k
}
251
252
size_t
253
loongarch_split_args_by_comma (char *args, const char *arg_strs[])
254
23.8k
{
255
23.8k
  size_t num = 0;
256
257
23.8k
  if (*args)
258
23.8k
    arg_strs[num++] = args;
259
424k
  for (; *args; args++)
260
401k
    if (*args == ',')
261
42.1k
      {
262
42.1k
  if (MAX_ARG_NUM_PLUS_2 - 1 == num)
263
0
    break;
264
42.1k
  else
265
42.1k
    *args = '\0', arg_strs[num++] = args + 1;
266
42.1k
      }
267
23.8k
  arg_strs[num] = NULL;
268
23.8k
  return num;
269
23.8k
}
270
271
char *
272
loongarch_cat_splited_strs (const char *arg_strs[])
273
0
{
274
0
  char *ret;
275
0
  size_t n, l;
276
277
0
  for (l = 0, n = 0; arg_strs[n]; n++)
278
0
    l += strlen (arg_strs[n]);
279
0
  ret = malloc (l + n + 1);
280
0
  if (!ret)
281
0
    return ret;
282
283
0
  ret[0] = '\0';
284
0
  if (0 < n)
285
0
    strcat (ret, arg_strs[0]);
286
0
  for (l = 1; l < n; l++)
287
0
    strcat (ret, ","), strcat (ret, arg_strs[l]);
288
0
  return ret;
289
0
}
290
291
insn_t
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),
296
      void *context)
297
23.8k
{
298
23.8k
  char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
299
23.8k
  const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
300
23.8k
  size_t i;
301
23.8k
  insn_t ret = 0;
302
23.8k
  int ok;
303
304
23.8k
  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
89.9k
  for (i = 0; esc1s[i] && arg_strs[i]; i++)
308
66.0k
    ;
309
23.8k
  ok = ok && !esc1s[i] && !arg_strs[i];
310
311
23.8k
  if (ok && helper)
312
23.8k
    {
313
89.9k
      for (i = 0; arg_strs[i]; i++)
314
66.0k
  ret |= loongarch_encode_imm (bit_fields[i],
315
66.0k
             helper (esc1s[i], esc2s[i],
316
66.0k
               bit_fields[i], arg_strs[i],
317
66.0k
               context));
318
23.8k
      ret |= helper ('\0', '\0', NULL, NULL, context);
319
23.8k
    }
320
321
23.8k
  return ret;
322
23.8k
}
323
324
int
325
loongarch_check_format (const char *format)
326
0
{
327
0
  char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
328
0
  const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
329
330
0
  if (!format)
331
0
    return -1;
332
333
0
  return loongarch_parse_format (format, esc1s, esc2s, bit_fields);
334
0
}
335
336
int
337
loongarch_check_macro (const char *format, const char *macro)
338
0
{
339
0
  int num_of_args;
340
0
  char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
341
0
  const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
342
343
0
  if (!format || !macro
344
0
      || loongarch_parse_format (format, esc1s, esc2s, bit_fields) != 0)
345
0
    return -1;
346
347
0
  for (num_of_args = 0; esc1s[num_of_args]; num_of_args++)
348
0
    ;
349
350
0
  for (; macro[0]; macro++)
351
0
    if (macro[0] == '%')
352
0
      {
353
0
  macro++;
354
0
  if ('1' <= macro[0] && macro[0] <= '9')
355
0
    {
356
0
      if (num_of_args < macro[0] - '0')
357
        /* Out of args num.  */
358
0
        return -1;
359
0
    }
360
0
  else if (macro[0] == 'f')
361
0
    ;
362
0
  else if (macro[0] == '%')
363
0
    ;
364
0
  else
365
0
    return -1;
366
0
      }
367
0
  return 0;
368
0
}
369
370
static const char *
371
I (char esc_ch1 ATTRIBUTE_UNUSED, char esc_ch2 ATTRIBUTE_UNUSED,
372
   const char *c_str)
373
0
{
374
0
  return c_str;
375
0
}
376
377
char *
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,
382
  size_t len_str)
383
0
{
384
0
  char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
385
0
  const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
386
0
  const char *src;
387
0
  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
0
  char *buffer =(char *) malloc(1024 +  6 * len_str);
393
394
0
  if (format)
395
0
    loongarch_parse_format (format, esc1s, esc2s, bit_fields);
396
397
0
  src = macro;
398
0
  dest = buffer;
399
400
0
  while (*src)
401
0
    if (*src == '%')
402
0
      {
403
0
  src++;
404
0
  if ('1' <= *src && *src <= '9')
405
0
    {
406
0
      size_t i = *src - '1';
407
0
      const char *t = map (esc1s[i], esc2s[i], arg_strs[i]);
408
0
      while (*t)
409
0
        *dest++ = *t++;
410
0
    }
411
0
  else if (*src == '%')
412
0
    *dest++ = '%';
413
0
  else if (*src == 'f' && helper)
414
0
    {
415
0
      char *b, *t;
416
0
      t = b = (*helper) (arg_strs, context);
417
0
      if (b)
418
0
        {
419
0
    while (*t)
420
0
      *dest++ = *t++;
421
0
    free (b);
422
0
        }
423
0
    }
424
0
  src++;
425
0
      }
426
0
    else
427
0
      *dest++ = *src++;
428
429
0
  *dest = '\0';
430
0
  return buffer;
431
0
}
432
433
char *
434
loongarch_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
0
{
439
0
  return loongarch_expand_macro_with_format_map (NULL, macro, arg_strs, I,
440
0
             helper, context, len_str);
441
0
}
442
443
size_t
444
loongarch_bits_imm_needed (int64_t imm, int si)
445
0
{
446
0
  size_t ret;
447
0
  if (si)
448
0
    {
449
0
      if (imm < 0)
450
0
  {
451
0
    uint64_t uimm = (uint64_t) imm;
452
0
    uint64_t uimax = UINT64_C (1) << 63;
453
0
    for (ret = 0; (uimm & uimax) != 0; uimm <<= 1, ret++)
454
0
      ;
455
0
    ret = 64 - ret + 1;
456
0
  }
457
0
      else
458
0
  ret = loongarch_bits_imm_needed (imm, 0) + 1;
459
0
    }
460
0
  else
461
0
    {
462
0
      uint64_t t = imm;
463
0
      for (ret = 0; t; t >>= 1, ret++)
464
0
  ;
465
0
    }
466
0
  return ret;
467
0
}
468
469
void
470
loongarch_eliminate_adjacent_repeat_char (char *dest, char c)
471
0
{
472
0
  if (c == '\0')
473
0
    return;
474
0
  char *src = dest;
475
0
  while (*dest)
476
0
    {
477
0
      while (src[0] == c && src[0] == src[1])
478
0
  src++;
479
0
      *dest++ = *src++;
480
0
    }
481
0
}