Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/opcodes/frv-asm.c
Line
Count
Source (jump to first uncovered line)
1
/* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
2
/* Assembler interface for targets using CGEN. -*- C -*-
3
   CGEN: Cpu tools GENerator
4
5
   THIS FILE IS MACHINE GENERATED WITH CGEN.
6
   - the resultant file is machine generated, cgen-asm.in isn't
7
8
   Copyright (C) 1996-2025 Free Software Foundation, Inc.
9
10
   This file is part of libopcodes.
11
12
   This library is free software; you can redistribute it and/or modify
13
   it under the terms of the GNU General Public License as published by
14
   the Free Software Foundation; either version 3, or (at your option)
15
   any later version.
16
17
   It is distributed in the hope that it will be useful, but WITHOUT
18
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
20
   License for more details.
21
22
   You should have received a copy of the GNU General Public License
23
   along with this program; if not, write to the Free Software Foundation, Inc.,
24
   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
25
26
27
/* ??? Eventually more and more of this stuff can go to cpu-independent files.
28
   Keep that in mind.  */
29
30
#include "sysdep.h"
31
#include <stdio.h>
32
#include "ansidecl.h"
33
#include "bfd.h"
34
#include "symcat.h"
35
#include "frv-desc.h"
36
#include "frv-opc.h"
37
#include "opintl.h"
38
#include "xregex.h"
39
#include "libiberty.h"
40
#include "safe-ctype.h"
41
42
#undef  min
43
#define min(a,b) ((a) < (b) ? (a) : (b))
44
#undef  max
45
#define max(a,b) ((a) > (b) ? (a) : (b))
46
47
static const char * parse_insn_normal
48
  (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
49

50
/* -- assembler routines inserted here.  */
51
52
/* -- asm.c */
53
inline static const char *
54
parse_symbolic_address (CGEN_CPU_DESC cd,
55
      const char **strp,
56
      int opindex,
57
      int opinfo,
58
      enum cgen_parse_operand_result *resultp,
59
      bfd_vma *valuep)
60
0
{
61
0
  enum cgen_parse_operand_result result_type;
62
0
  const char *errmsg = (* cd->parse_operand_fn)
63
0
    (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
64
0
     &result_type, valuep);
65
66
0
  if (errmsg == NULL
67
0
      && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
68
0
    return "symbolic expression required";
69
70
0
  if (resultp)
71
0
    *resultp = result_type;
72
73
0
  return errmsg;
74
0
}
75
76
static const char *
77
parse_ldd_annotation (CGEN_CPU_DESC cd,
78
          const char **strp,
79
          int opindex,
80
          unsigned long *valuep)
81
0
{
82
0
  const char *errmsg;
83
0
  enum cgen_parse_operand_result result_type;
84
0
  bfd_vma value;
85
86
0
  if (**strp == '#' || **strp == '%')
87
0
    {
88
0
      if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
89
0
  {
90
0
    *strp += 9;
91
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
92
0
             BFD_RELOC_FRV_TLSDESC_RELAX,
93
0
             &result_type, &value);
94
0
    if (**strp != ')')
95
0
      return "missing ')'";
96
0
    if (valuep)
97
0
      *valuep = value;
98
0
    ++*strp;
99
0
    if (errmsg)
100
0
      return errmsg;
101
0
  }
102
0
    }
103
104
0
  while (**strp == ' ' || **strp == '\t')
105
0
    ++*strp;
106
107
0
  if (**strp != '@')
108
0
    return "missing `@'";
109
110
0
  ++*strp;
111
112
0
  return NULL;
113
0
}
114
115
static const char *
116
parse_call_annotation (CGEN_CPU_DESC cd,
117
           const char **strp,
118
           int opindex,
119
           unsigned long *valuep)
120
0
{
121
0
  const char *errmsg;
122
0
  enum cgen_parse_operand_result result_type;
123
0
  bfd_vma value;
124
125
0
  if (**strp == '#' || **strp == '%')
126
0
    {
127
0
      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
128
0
  {
129
0
    *strp += 11;
130
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
131
0
             BFD_RELOC_FRV_GETTLSOFF_RELAX,
132
0
             &result_type, &value);
133
0
    if (**strp != ')')
134
0
      return "missing ')'";
135
0
    if (valuep)
136
0
      *valuep = value;
137
0
    ++*strp;
138
0
    if (errmsg)
139
0
      return errmsg;
140
0
  }
141
0
    }
142
143
0
  while (**strp == ' ' || **strp == '\t')
144
0
    ++*strp;
145
146
0
  if (**strp != '@')
147
0
    return "missing `@'";
148
149
0
  ++*strp;
150
151
0
  return NULL;
152
0
}
153
154
static const char *
155
parse_ld_annotation (CGEN_CPU_DESC cd,
156
         const char **strp,
157
         int opindex,
158
         unsigned long *valuep)
159
0
{
160
0
  const char *errmsg;
161
0
  enum cgen_parse_operand_result result_type;
162
0
  bfd_vma value;
163
164
0
  if (**strp == '#' || **strp == '%')
165
0
    {
166
0
      if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
167
0
  {
168
0
    *strp += 8;
169
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
170
0
             BFD_RELOC_FRV_TLSOFF_RELAX,
171
0
             &result_type, &value);
172
0
    if (**strp != ')')
173
0
      return "missing ')'";
174
0
    if (valuep)
175
0
      *valuep = value;
176
0
    ++*strp;
177
0
    if (errmsg)
178
0
      return errmsg;
179
0
  }
180
0
    }
181
182
0
  while (**strp == ' ' || **strp == '\t')
183
0
    ++*strp;
184
185
0
  if (**strp != '@')
186
0
    return "missing `@'";
187
188
0
  ++*strp;
189
190
0
  return NULL;
191
0
}
192
193
static const char *
194
parse_ulo16 (CGEN_CPU_DESC cd,
195
       const char **strp,
196
       int opindex,
197
       unsigned long *valuep)
198
0
{
199
0
  const char *errmsg;
200
0
  enum cgen_parse_operand_result result_type;
201
0
  bfd_vma value;
202
203
0
  if (**strp == '#' || **strp == '%')
204
0
    {
205
0
      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
206
0
  {
207
0
    *strp += 4;
208
0
    errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
209
0
               & result_type, & value);
210
0
    if (**strp != ')')
211
0
      return "missing `)'";
212
0
    ++*strp;
213
0
    if (errmsg == NULL
214
0
        && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
215
0
      value &= 0xffff;
216
0
    *valuep = value;
217
0
    return errmsg;
218
0
  }
219
0
      if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
220
0
  {
221
0
    *strp += 9;
222
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
223
0
             BFD_RELOC_FRV_GPRELLO,
224
0
             & result_type, & value);
225
0
    if (**strp != ')')
226
0
      return "missing ')'";
227
0
    ++*strp;
228
0
    *valuep = value;
229
0
    return errmsg;
230
0
  }
231
0
      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
232
0
  {
233
0
    *strp += 7;
234
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
235
0
             BFD_RELOC_FRV_GOTLO,
236
0
             & result_type, & value);
237
0
    if (**strp != ')')
238
0
      return "missing ')'";
239
0
    ++*strp;
240
0
    *valuep = value;
241
0
    return errmsg;
242
0
  }
243
0
      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
244
0
  {
245
0
    *strp += 15;
246
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
247
0
             BFD_RELOC_FRV_FUNCDESC_GOTLO,
248
0
             & result_type, & value);
249
0
    if (**strp != ')')
250
0
      return "missing ')'";
251
0
    ++*strp;
252
0
    *valuep = value;
253
0
    return errmsg;
254
0
  }
255
0
      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
256
0
  {
257
0
    *strp += 10;
258
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
259
0
             BFD_RELOC_FRV_GOTOFFLO,
260
0
             & result_type, & value);
261
0
    if (**strp != ')')
262
0
      return "missing ')'";
263
0
    ++*strp;
264
0
    *valuep = value;
265
0
    return errmsg;
266
0
  }
267
0
      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
268
0
  {
269
0
    *strp += 18;
270
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
271
0
             BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
272
0
             & result_type, & value);
273
0
    if (**strp != ')')
274
0
      return "missing ')'";
275
0
    ++*strp;
276
0
    *valuep = value;
277
0
    return errmsg;
278
0
  }
279
0
      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
280
0
  {
281
0
    *strp += 14;
282
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
283
0
             BFD_RELOC_FRV_GOTTLSDESCLO,
284
0
             & result_type, & value);
285
0
    if (**strp != ')')
286
0
      return "missing ')'";
287
0
    ++*strp;
288
0
    *valuep = value;
289
0
    return errmsg;
290
0
  }
291
0
      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
292
0
  {
293
0
    *strp += 11;
294
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
295
0
             BFD_RELOC_FRV_TLSMOFFLO,
296
0
             & result_type, & value);
297
0
    if (**strp != ')')
298
0
      return "missing ')'";
299
0
    ++*strp;
300
0
    *valuep = value;
301
0
    return errmsg;
302
0
  }
303
0
      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
304
0
  {
305
0
    *strp += 13;
306
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
307
0
             BFD_RELOC_FRV_GOTTLSOFFLO,
308
0
             & result_type, & value);
309
0
    if (**strp != ')')
310
0
      return "missing ')'";
311
0
    ++*strp;
312
0
    *valuep = value;
313
0
    return errmsg;
314
0
  }
315
0
    }
316
0
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
317
0
}
318
319
static const char *
320
parse_uslo16 (CGEN_CPU_DESC cd,
321
        const char **strp,
322
        int opindex,
323
        signed long *valuep)
324
0
{
325
0
  const char *errmsg;
326
0
  enum cgen_parse_operand_result result_type;
327
0
  bfd_vma value;
328
329
0
  if (**strp == '#' || **strp == '%')
330
0
    {
331
0
      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
332
0
  {
333
0
    *strp += 4;
334
0
    errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
335
0
               & result_type, & value);
336
0
    if (**strp != ')')
337
0
      return "missing `)'";
338
0
    ++*strp;
339
0
    if (errmsg == NULL
340
0
        && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
341
0
      value &= 0xffff;
342
0
    *valuep = value;
343
0
    return errmsg;
344
0
  }
345
0
      else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
346
0
  {
347
0
    *strp += 9;
348
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
349
0
             BFD_RELOC_FRV_GPRELLO,
350
0
             & result_type, & value);
351
0
    if (**strp != ')')
352
0
      return "missing ')'";
353
0
    ++*strp;
354
0
    *valuep = value;
355
0
    return errmsg;
356
0
  }
357
0
      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
358
0
  {
359
0
    *strp += 7;
360
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
361
0
             BFD_RELOC_FRV_GOTLO,
362
0
             & result_type, & value);
363
0
    if (**strp != ')')
364
0
      return "missing ')'";
365
0
    ++*strp;
366
0
    *valuep = value;
367
0
    return errmsg;
368
0
  }
369
0
      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
370
0
  {
371
0
    *strp += 15;
372
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
373
0
             BFD_RELOC_FRV_FUNCDESC_GOTLO,
374
0
             & result_type, & value);
375
0
    if (**strp != ')')
376
0
      return "missing ')'";
377
0
    ++*strp;
378
0
    *valuep = value;
379
0
    return errmsg;
380
0
  }
381
0
      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
382
0
  {
383
0
    *strp += 10;
384
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
385
0
             BFD_RELOC_FRV_GOTOFFLO,
386
0
             & result_type, & value);
387
0
    if (**strp != ')')
388
0
      return "missing ')'";
389
0
    ++*strp;
390
0
    *valuep = value;
391
0
    return errmsg;
392
0
  }
393
0
      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
394
0
  {
395
0
    *strp += 18;
396
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
397
0
             BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
398
0
             & result_type, & value);
399
0
    if (**strp != ')')
400
0
      return "missing ')'";
401
0
    ++*strp;
402
0
    *valuep = value;
403
0
    return errmsg;
404
0
  }
405
0
      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
406
0
  {
407
0
    *strp += 14;
408
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
409
0
             BFD_RELOC_FRV_GOTTLSDESCLO,
410
0
             & result_type, & value);
411
0
    if (**strp != ')')
412
0
      return "missing ')'";
413
0
    ++*strp;
414
0
    *valuep = value;
415
0
    return errmsg;
416
0
  }
417
0
      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
418
0
  {
419
0
    *strp += 11;
420
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
421
0
             BFD_RELOC_FRV_TLSMOFFLO,
422
0
             & result_type, & value);
423
0
    if (**strp != ')')
424
0
      return "missing ')'";
425
0
    ++*strp;
426
0
    *valuep = value;
427
0
    return errmsg;
428
0
  }
429
0
      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
430
0
  {
431
0
    *strp += 13;
432
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
433
0
             BFD_RELOC_FRV_GOTTLSOFFLO,
434
0
             & result_type, & value);
435
0
    if (**strp != ')')
436
0
      return "missing ')'";
437
0
    ++*strp;
438
0
    *valuep = value;
439
0
    return errmsg;
440
0
  }
441
0
    }
442
0
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
443
0
}
444
445
static const char *
446
parse_uhi16 (CGEN_CPU_DESC cd,
447
       const char **strp,
448
       int opindex,
449
       unsigned long *valuep)
450
0
{
451
0
  const char *errmsg;
452
0
  enum cgen_parse_operand_result result_type;
453
0
  bfd_vma value;
454
455
0
  if (**strp == '#' || **strp == '%')
456
0
    {
457
0
      if (strncasecmp (*strp + 1, "hi(", 3) == 0)
458
0
  {
459
0
    *strp += 4;
460
0
    errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
461
0
               & result_type, & value);
462
0
    if (**strp != ')')
463
0
      return "missing `)'";
464
0
    ++*strp;
465
0
    if (errmsg == NULL
466
0
        && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
467
0
      {
468
        /* If value is wider than 32 bits then be
469
     careful about how we extract bits 16-31.  */
470
0
        if (sizeof (value) > 4)
471
0
    value &= (((bfd_vma)1 << 16) << 16) - 1;
472
473
0
        value >>= 16;
474
0
      }
475
0
    *valuep = value;
476
0
    return errmsg;
477
0
  }
478
0
      else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
479
0
  {
480
0
    *strp += 9;
481
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
482
0
             BFD_RELOC_FRV_GPRELHI,
483
0
             & result_type, & value);
484
0
    if (**strp != ')')
485
0
      return "missing ')'";
486
0
    ++*strp;
487
0
    *valuep = value;
488
0
    return errmsg;
489
0
  }
490
0
      else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
491
0
  {
492
0
    *strp += 7;
493
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
494
0
             BFD_RELOC_FRV_GOTHI,
495
0
             & result_type, & value);
496
0
    if (**strp != ')')
497
0
      return "missing ')'";
498
0
    ++*strp;
499
0
    *valuep = value;
500
0
    return errmsg;
501
0
  }
502
0
      else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
503
0
  {
504
0
    *strp += 15;
505
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
506
0
             BFD_RELOC_FRV_FUNCDESC_GOTHI,
507
0
             & result_type, & value);
508
0
    if (**strp != ')')
509
0
      return "missing ')'";
510
0
    ++*strp;
511
0
    *valuep = value;
512
0
    return errmsg;
513
0
  }
514
0
      else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
515
0
  {
516
0
    *strp += 10;
517
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
518
0
             BFD_RELOC_FRV_GOTOFFHI,
519
0
             & result_type, & value);
520
0
    if (**strp != ')')
521
0
      return "missing ')'";
522
0
    ++*strp;
523
0
    *valuep = value;
524
0
    return errmsg;
525
0
  }
526
0
      else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
527
0
  {
528
0
    *strp += 18;
529
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
530
0
             BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
531
0
             & result_type, & value);
532
0
    if (**strp != ')')
533
0
      return "missing ')'";
534
0
    ++*strp;
535
0
    *valuep = value;
536
0
    return errmsg;
537
0
  }
538
0
      else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
539
0
  {
540
0
    *strp += 14;
541
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
542
0
             BFD_RELOC_FRV_GOTTLSDESCHI,
543
0
             &result_type, &value);
544
0
    if (**strp != ')')
545
0
      return "missing ')'";
546
0
    ++*strp;
547
0
    *valuep = value;
548
0
    return errmsg;
549
0
  }
550
0
      else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
551
0
  {
552
0
    *strp += 11;
553
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
554
0
             BFD_RELOC_FRV_TLSMOFFHI,
555
0
             & result_type, & value);
556
0
    if (**strp != ')')
557
0
      return "missing ')'";
558
0
    ++*strp;
559
0
    *valuep = value;
560
0
    return errmsg;
561
0
  }
562
0
      else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
563
0
  {
564
0
    *strp += 13;
565
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
566
0
             BFD_RELOC_FRV_GOTTLSOFFHI,
567
0
             & result_type, & value);
568
0
    if (**strp != ')')
569
0
      return "missing ')'";
570
0
    ++*strp;
571
0
    *valuep = value;
572
0
    return errmsg;
573
0
  }
574
0
    }
575
0
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
576
0
}
577
578
static long
579
parse_register_number (const char **strp)
580
0
{
581
0
  int regno;
582
583
0
  if (**strp < '0' || **strp > '9')
584
0
    return -1; /* error */
585
586
0
  regno = **strp - '0';
587
0
  for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
588
0
    regno = regno * 10 + (**strp - '0');
589
590
0
  return regno;
591
0
}
592
593
static const char *
594
parse_spr (CGEN_CPU_DESC cd,
595
     const char **strp,
596
     CGEN_KEYWORD * table,
597
     long *valuep)
598
0
{
599
0
  const char *save_strp;
600
0
  long regno;
601
602
  /* Check for spr index notation.  */
603
0
  if (strncasecmp (*strp, "spr[", 4) == 0)
604
0
    {
605
0
      *strp += 4;
606
0
      regno = parse_register_number (strp);
607
0
      if (**strp != ']')
608
0
        return _("missing `]'");
609
0
      ++*strp;
610
0
      if (! spr_valid (regno))
611
0
  return _("Special purpose register number is out of range");
612
0
      *valuep = regno;
613
0
      return NULL;
614
0
    }
615
616
0
  save_strp = *strp;
617
0
  regno = parse_register_number (strp);
618
0
  if (regno != -1)
619
0
    {
620
0
      if (! spr_valid (regno))
621
0
  return _("Special purpose register number is out of range");
622
0
      *valuep = regno;
623
0
      return NULL;
624
0
    }
625
626
0
  *strp = save_strp;
627
0
  return cgen_parse_keyword (cd, strp, table, valuep);
628
0
}
629
630
static const char *
631
parse_d12 (CGEN_CPU_DESC cd,
632
     const char **strp,
633
     int opindex,
634
     long *valuep)
635
0
{
636
0
  const char *errmsg;
637
0
  enum cgen_parse_operand_result result_type;
638
0
  bfd_vma value;
639
640
  /* Check for small data reference.  */
641
0
  if (**strp == '#' || **strp == '%')
642
0
    {
643
0
      if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
644
0
        {
645
0
          *strp += 9;
646
0
          errmsg = parse_symbolic_address (cd, strp, opindex,
647
0
             BFD_RELOC_FRV_GPREL12,
648
0
             & result_type, & value);
649
0
          if (**strp != ')')
650
0
            return "missing `)'";
651
0
          ++*strp;
652
0
          *valuep = value;
653
0
          return errmsg;
654
0
        }
655
0
      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
656
0
  {
657
0
    *strp += 7;
658
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
659
0
             BFD_RELOC_FRV_GOT12,
660
0
             & result_type, & value);
661
0
    if (**strp != ')')
662
0
      return "missing ')'";
663
0
    ++*strp;
664
0
    *valuep = value;
665
0
    return errmsg;
666
0
  }
667
0
      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
668
0
  {
669
0
    *strp += 15;
670
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
671
0
             BFD_RELOC_FRV_FUNCDESC_GOT12,
672
0
             & result_type, & value);
673
0
    if (**strp != ')')
674
0
      return "missing ')'";
675
0
    ++*strp;
676
0
    *valuep = value;
677
0
    return errmsg;
678
0
  }
679
0
      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
680
0
  {
681
0
    *strp += 10;
682
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
683
0
             BFD_RELOC_FRV_GOTOFF12,
684
0
             & result_type, & value);
685
0
    if (**strp != ')')
686
0
      return "missing ')'";
687
0
    ++*strp;
688
0
    *valuep = value;
689
0
    return errmsg;
690
0
  }
691
0
      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
692
0
  {
693
0
    *strp += 18;
694
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
695
0
             BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
696
0
             & result_type, & value);
697
0
    if (**strp != ')')
698
0
      return "missing ')'";
699
0
    ++*strp;
700
0
    *valuep = value;
701
0
    return errmsg;
702
0
  }
703
0
      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
704
0
  {
705
0
    *strp += 14;
706
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
707
0
             BFD_RELOC_FRV_GOTTLSDESC12,
708
0
             & result_type, & value);
709
0
    if (**strp != ')')
710
0
      return "missing ')'";
711
0
    ++*strp;
712
0
    *valuep = value;
713
0
    return errmsg;
714
0
  }
715
0
      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
716
0
  {
717
0
    *strp += 11;
718
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
719
0
             BFD_RELOC_FRV_TLSMOFF12,
720
0
             & result_type, & value);
721
0
    if (**strp != ')')
722
0
      return "missing ')'";
723
0
    ++*strp;
724
0
    *valuep = value;
725
0
    return errmsg;
726
0
  }
727
0
      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
728
0
  {
729
0
    *strp += 13;
730
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
731
0
             BFD_RELOC_FRV_GOTTLSOFF12,
732
0
             & result_type, & value);
733
0
    if (**strp != ')')
734
0
      return "missing ')'";
735
0
    ++*strp;
736
0
    *valuep = value;
737
0
    return errmsg;
738
0
  }
739
0
    }
740
0
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
741
0
}
742
743
static const char *
744
parse_s12 (CGEN_CPU_DESC cd,
745
     const char **strp,
746
     int opindex,
747
     long *valuep)
748
0
{
749
0
  const char *errmsg;
750
0
  enum cgen_parse_operand_result result_type;
751
0
  bfd_vma value;
752
753
  /* Check for small data reference.  */
754
0
  if (**strp == '#' || **strp == '%')
755
0
    {
756
0
      if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
757
0
  {
758
0
    *strp += 9;
759
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
760
0
             BFD_RELOC_FRV_GPREL12,
761
0
             & result_type, & value);
762
0
    if (**strp != ')')
763
0
      return "missing `)'";
764
0
    ++*strp;
765
0
    *valuep = value;
766
0
    return errmsg;
767
0
  }
768
0
      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
769
0
  {
770
0
    *strp += 7;
771
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
772
0
             BFD_RELOC_FRV_GOT12,
773
0
             & result_type, & value);
774
0
    if (**strp != ')')
775
0
      return "missing ')'";
776
0
    ++*strp;
777
0
    *valuep = value;
778
0
    return errmsg;
779
0
  }
780
0
      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
781
0
  {
782
0
    *strp += 15;
783
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
784
0
             BFD_RELOC_FRV_FUNCDESC_GOT12,
785
0
             & result_type, & value);
786
0
    if (**strp != ')')
787
0
      return "missing ')'";
788
0
    ++*strp;
789
0
    *valuep = value;
790
0
    return errmsg;
791
0
  }
792
0
      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
793
0
  {
794
0
    *strp += 10;
795
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
796
0
             BFD_RELOC_FRV_GOTOFF12,
797
0
             & result_type, & value);
798
0
    if (**strp != ')')
799
0
      return "missing ')'";
800
0
    ++*strp;
801
0
    *valuep = value;
802
0
    return errmsg;
803
0
  }
804
0
      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
805
0
  {
806
0
    *strp += 18;
807
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
808
0
             BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
809
0
             & result_type, & value);
810
0
    if (**strp != ')')
811
0
      return "missing ')'";
812
0
    ++*strp;
813
0
    *valuep = value;
814
0
    return errmsg;
815
0
  }
816
0
      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
817
0
  {
818
0
    *strp += 14;
819
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
820
0
             BFD_RELOC_FRV_GOTTLSDESC12,
821
0
             & result_type, & value);
822
0
    if (**strp != ')')
823
0
      return "missing ')'";
824
0
    ++*strp;
825
0
    *valuep = value;
826
0
    return errmsg;
827
0
  }
828
0
      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
829
0
  {
830
0
    *strp += 11;
831
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
832
0
             BFD_RELOC_FRV_TLSMOFF12,
833
0
             & result_type, & value);
834
0
    if (**strp != ')')
835
0
      return "missing ')'";
836
0
    ++*strp;
837
0
    *valuep = value;
838
0
    return errmsg;
839
0
  }
840
0
      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
841
0
  {
842
0
    *strp += 13;
843
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
844
0
             BFD_RELOC_FRV_GOTTLSOFF12,
845
0
             & result_type, & value);
846
0
    if (**strp != ')')
847
0
      return "missing ')'";
848
0
    ++*strp;
849
0
    *valuep = value;
850
0
    return errmsg;
851
0
  }
852
0
    }
853
854
0
  if (**strp == '#')
855
0
    ++*strp;
856
0
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
857
0
}
858
859
static const char *
860
parse_u12 (CGEN_CPU_DESC cd,
861
     const char **strp,
862
     int opindex,
863
     long *valuep)
864
0
{
865
0
  const char *errmsg;
866
0
  enum cgen_parse_operand_result result_type;
867
0
  bfd_vma value;
868
869
  /* Check for small data reference.  */
870
0
  if ((**strp == '#' || **strp == '%')
871
0
      && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
872
0
    {
873
0
      *strp += 9;
874
0
      errmsg = parse_symbolic_address (cd, strp, opindex,
875
0
               BFD_RELOC_FRV_GPRELU12,
876
0
               & result_type, & value);
877
0
      if (**strp != ')')
878
0
        return "missing `)'";
879
0
      ++*strp;
880
0
      *valuep = value;
881
0
      return errmsg;
882
0
    }
883
0
  else
884
0
    {
885
0
      if (**strp == '#')
886
0
        ++*strp;
887
0
      return cgen_parse_signed_integer (cd, strp, opindex, valuep);
888
0
    }
889
0
}
890
891
static const char *
892
parse_A (CGEN_CPU_DESC cd,
893
   const char **strp,
894
   int opindex,
895
   unsigned long *valuep,
896
   unsigned long A)
897
0
{
898
0
  const char *errmsg;
899
900
0
  if (**strp == '#')
901
0
    ++*strp;
902
903
0
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
904
0
  if (errmsg)
905
0
    return errmsg;
906
907
0
  if (*valuep != A)
908
0
    return _("Value of A operand must be 0 or 1");
909
910
0
  return NULL;
911
0
}
912
913
static const char *
914
parse_A0 (CGEN_CPU_DESC cd,
915
    const char **strp,
916
    int opindex,
917
    unsigned long *valuep)
918
0
{
919
0
  return parse_A (cd, strp, opindex, valuep, 0);
920
0
}
921
922
static const char *
923
parse_A1 (CGEN_CPU_DESC cd,
924
    const char **strp,
925
    int opindex,
926
    unsigned long *valuep)
927
0
{
928
0
  return parse_A (cd, strp, opindex, valuep, 1);
929
0
}
930
931
static const char *
932
parse_even_register (CGEN_CPU_DESC  cd,
933
         const char **  strP,
934
         CGEN_KEYWORD * tableP,
935
         long *         valueP)
936
0
{
937
0
  const char * errmsg;
938
0
  const char * saved_star_strP = * strP;
939
940
0
  errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
941
942
0
  if (errmsg == NULL && ((* valueP) & 1))
943
0
    {
944
0
      errmsg = _("register number must be even");
945
0
      * strP = saved_star_strP;
946
0
    }
947
948
0
  return errmsg;
949
0
}
950
951
static const char *
952
parse_call_label (CGEN_CPU_DESC cd,
953
      const char **strp,
954
      int opindex,
955
      int opinfo,
956
      enum cgen_parse_operand_result *resultp,
957
      bfd_vma *valuep)
958
0
{
959
0
  const char *errmsg;
960
0
  bfd_vma value;
961
962
  /* Check for small data reference.  */
963
0
  if (opinfo == 0 && (**strp == '#' || **strp == '%'))
964
0
    {
965
0
      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
966
0
  {
967
0
    *strp += 11;
968
0
    errmsg = parse_symbolic_address (cd, strp, opindex,
969
0
             BFD_RELOC_FRV_GETTLSOFF,
970
0
             resultp, &value);
971
0
    if (**strp != ')')
972
0
      return _("missing `)'");
973
0
    ++*strp;
974
0
    *valuep = value;
975
0
    return errmsg;
976
0
  }
977
0
    }
978
979
0
  return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
980
0
}
981
982
/* -- */
983
984
const char * frv_cgen_parse_operand
985
  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
986
987
/* Main entry point for operand parsing.
988
989
   This function is basically just a big switch statement.  Earlier versions
990
   used tables to look up the function to use, but
991
   - if the table contains both assembler and disassembler functions then
992
     the disassembler contains much of the assembler and vice-versa,
993
   - there's a lot of inlining possibilities as things grow,
994
   - using a switch statement avoids the function call overhead.
995
996
   This function could be moved into `parse_insn_normal', but keeping it
997
   separate makes clear the interface between `parse_insn_normal' and each of
998
   the handlers.  */
999
1000
const char *
1001
frv_cgen_parse_operand (CGEN_CPU_DESC cd,
1002
         int opindex,
1003
         const char ** strp,
1004
         CGEN_FIELDS * fields)
1005
0
{
1006
0
  const char * errmsg = NULL;
1007
  /* Used by scalar operands that still need to be parsed.  */
1008
0
  long junk ATTRIBUTE_UNUSED;
1009
1010
0
  switch (opindex)
1011
0
    {
1012
0
    case FRV_OPERAND_A0 :
1013
0
      errmsg = parse_A0 (cd, strp, FRV_OPERAND_A0, (unsigned long *) (& fields->f_A));
1014
0
      break;
1015
0
    case FRV_OPERAND_A1 :
1016
0
      errmsg = parse_A1 (cd, strp, FRV_OPERAND_A1, (unsigned long *) (& fields->f_A));
1017
0
      break;
1018
0
    case FRV_OPERAND_ACC40SI :
1019
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Si);
1020
0
      break;
1021
0
    case FRV_OPERAND_ACC40SK :
1022
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Sk);
1023
0
      break;
1024
0
    case FRV_OPERAND_ACC40UI :
1025
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Ui);
1026
0
      break;
1027
0
    case FRV_OPERAND_ACC40UK :
1028
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Uk);
1029
0
      break;
1030
0
    case FRV_OPERAND_ACCGI :
1031
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGi);
1032
0
      break;
1033
0
    case FRV_OPERAND_ACCGK :
1034
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGk);
1035
0
      break;
1036
0
    case FRV_OPERAND_CCI :
1037
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CCi);
1038
0
      break;
1039
0
    case FRV_OPERAND_CPRDOUBLEK :
1040
0
      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
1041
0
      break;
1042
0
    case FRV_OPERAND_CPRI :
1043
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRi);
1044
0
      break;
1045
0
    case FRV_OPERAND_CPRJ :
1046
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRj);
1047
0
      break;
1048
0
    case FRV_OPERAND_CPRK :
1049
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
1050
0
      break;
1051
0
    case FRV_OPERAND_CRI :
1052
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRi);
1053
0
      break;
1054
0
    case FRV_OPERAND_CRJ :
1055
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj);
1056
0
      break;
1057
0
    case FRV_OPERAND_CRJ_FLOAT :
1058
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_float);
1059
0
      break;
1060
0
    case FRV_OPERAND_CRJ_INT :
1061
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_int);
1062
0
      break;
1063
0
    case FRV_OPERAND_CRK :
1064
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRk);
1065
0
      break;
1066
0
    case FRV_OPERAND_FCCI_1 :
1067
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_1);
1068
0
      break;
1069
0
    case FRV_OPERAND_FCCI_2 :
1070
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_2);
1071
0
      break;
1072
0
    case FRV_OPERAND_FCCI_3 :
1073
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_3);
1074
0
      break;
1075
0
    case FRV_OPERAND_FCCK :
1076
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCk);
1077
0
      break;
1078
0
    case FRV_OPERAND_FRDOUBLEI :
1079
0
      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
1080
0
      break;
1081
0
    case FRV_OPERAND_FRDOUBLEJ :
1082
0
      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
1083
0
      break;
1084
0
    case FRV_OPERAND_FRDOUBLEK :
1085
0
      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1086
0
      break;
1087
0
    case FRV_OPERAND_FRI :
1088
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
1089
0
      break;
1090
0
    case FRV_OPERAND_FRINTI :
1091
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
1092
0
      break;
1093
0
    case FRV_OPERAND_FRINTIEVEN :
1094
0
      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
1095
0
      break;
1096
0
    case FRV_OPERAND_FRINTJ :
1097
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
1098
0
      break;
1099
0
    case FRV_OPERAND_FRINTJEVEN :
1100
0
      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
1101
0
      break;
1102
0
    case FRV_OPERAND_FRINTK :
1103
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1104
0
      break;
1105
0
    case FRV_OPERAND_FRINTKEVEN :
1106
0
      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1107
0
      break;
1108
0
    case FRV_OPERAND_FRJ :
1109
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
1110
0
      break;
1111
0
    case FRV_OPERAND_FRK :
1112
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1113
0
      break;
1114
0
    case FRV_OPERAND_FRKHI :
1115
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1116
0
      break;
1117
0
    case FRV_OPERAND_FRKLO :
1118
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1119
0
      break;
1120
0
    case FRV_OPERAND_GRDOUBLEK :
1121
0
      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
1122
0
      break;
1123
0
    case FRV_OPERAND_GRI :
1124
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRi);
1125
0
      break;
1126
0
    case FRV_OPERAND_GRJ :
1127
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRj);
1128
0
      break;
1129
0
    case FRV_OPERAND_GRK :
1130
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
1131
0
      break;
1132
0
    case FRV_OPERAND_GRKHI :
1133
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
1134
0
      break;
1135
0
    case FRV_OPERAND_GRKLO :
1136
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
1137
0
      break;
1138
0
    case FRV_OPERAND_ICCI_1 :
1139
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_1);
1140
0
      break;
1141
0
    case FRV_OPERAND_ICCI_2 :
1142
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_2);
1143
0
      break;
1144
0
    case FRV_OPERAND_ICCI_3 :
1145
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_3);
1146
0
      break;
1147
0
    case FRV_OPERAND_LI :
1148
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LI, (unsigned long *) (& fields->f_LI));
1149
0
      break;
1150
0
    case FRV_OPERAND_LRAD :
1151
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAD, (unsigned long *) (& fields->f_LRAD));
1152
0
      break;
1153
0
    case FRV_OPERAND_LRAE :
1154
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAE, (unsigned long *) (& fields->f_LRAE));
1155
0
      break;
1156
0
    case FRV_OPERAND_LRAS :
1157
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAS, (unsigned long *) (& fields->f_LRAS));
1158
0
      break;
1159
0
    case FRV_OPERAND_TLBPRL :
1160
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPRL, (unsigned long *) (& fields->f_TLBPRL));
1161
0
      break;
1162
0
    case FRV_OPERAND_TLBPROPX :
1163
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPROPX, (unsigned long *) (& fields->f_TLBPRopx));
1164
0
      break;
1165
0
    case FRV_OPERAND_AE :
1166
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_AE, (unsigned long *) (& fields->f_ae));
1167
0
      break;
1168
0
    case FRV_OPERAND_CALLANN :
1169
0
      errmsg = parse_call_annotation (cd, strp, FRV_OPERAND_CALLANN, (unsigned long *) (& fields->f_reloc_ann));
1170
0
      break;
1171
0
    case FRV_OPERAND_CCOND :
1172
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_CCOND, (unsigned long *) (& fields->f_ccond));
1173
0
      break;
1174
0
    case FRV_OPERAND_COND :
1175
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_COND, (unsigned long *) (& fields->f_cond));
1176
0
      break;
1177
0
    case FRV_OPERAND_D12 :
1178
0
      errmsg = parse_d12 (cd, strp, FRV_OPERAND_D12, (long *) (& fields->f_d12));
1179
0
      break;
1180
0
    case FRV_OPERAND_DEBUG :
1181
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_DEBUG, (unsigned long *) (& fields->f_debug));
1182
0
      break;
1183
0
    case FRV_OPERAND_EIR :
1184
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_EIR, (unsigned long *) (& fields->f_eir));
1185
0
      break;
1186
0
    case FRV_OPERAND_HINT :
1187
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_HINT, (unsigned long *) (& fields->f_hint));
1188
0
      break;
1189
0
    case FRV_OPERAND_HINT_NOT_TAKEN :
1190
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_not_taken, & fields->f_hint);
1191
0
      break;
1192
0
    case FRV_OPERAND_HINT_TAKEN :
1193
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_taken, & fields->f_hint);
1194
0
      break;
1195
0
    case FRV_OPERAND_LABEL16 :
1196
0
      {
1197
0
        bfd_vma value = 0;
1198
0
        errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL16, 0, NULL,  & value);
1199
0
        fields->f_label16 = value;
1200
0
      }
1201
0
      break;
1202
0
    case FRV_OPERAND_LABEL24 :
1203
0
      {
1204
0
        bfd_vma value = 0;
1205
0
        errmsg = parse_call_label (cd, strp, FRV_OPERAND_LABEL24, 0, NULL,  & value);
1206
0
        fields->f_label24 = value;
1207
0
      }
1208
0
      break;
1209
0
    case FRV_OPERAND_LDANN :
1210
0
      errmsg = parse_ld_annotation (cd, strp, FRV_OPERAND_LDANN, (unsigned long *) (& fields->f_reloc_ann));
1211
0
      break;
1212
0
    case FRV_OPERAND_LDDANN :
1213
0
      errmsg = parse_ldd_annotation (cd, strp, FRV_OPERAND_LDDANN, (unsigned long *) (& fields->f_reloc_ann));
1214
0
      break;
1215
0
    case FRV_OPERAND_LOCK :
1216
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LOCK, (unsigned long *) (& fields->f_lock));
1217
0
      break;
1218
0
    case FRV_OPERAND_PACK :
1219
0
      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_pack, & fields->f_pack);
1220
0
      break;
1221
0
    case FRV_OPERAND_S10 :
1222
0
      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S10, (long *) (& fields->f_s10));
1223
0
      break;
1224
0
    case FRV_OPERAND_S12 :
1225
0
      errmsg = parse_s12 (cd, strp, FRV_OPERAND_S12, (long *) (& fields->f_d12));
1226
0
      break;
1227
0
    case FRV_OPERAND_S16 :
1228
0
      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S16, (long *) (& fields->f_s16));
1229
0
      break;
1230
0
    case FRV_OPERAND_S5 :
1231
0
      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S5, (long *) (& fields->f_s5));
1232
0
      break;
1233
0
    case FRV_OPERAND_S6 :
1234
0
      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6, (long *) (& fields->f_s6));
1235
0
      break;
1236
0
    case FRV_OPERAND_S6_1 :
1237
0
      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6_1, (long *) (& fields->f_s6_1));
1238
0
      break;
1239
0
    case FRV_OPERAND_SLO16 :
1240
0
      errmsg = parse_uslo16 (cd, strp, FRV_OPERAND_SLO16, (long *) (& fields->f_s16));
1241
0
      break;
1242
0
    case FRV_OPERAND_SPR :
1243
0
      errmsg = parse_spr (cd, strp, & frv_cgen_opval_spr_names, & fields->f_spr);
1244
0
      break;
1245
0
    case FRV_OPERAND_U12 :
1246
0
      errmsg = parse_u12 (cd, strp, FRV_OPERAND_U12, (long *) (& fields->f_u12));
1247
0
      break;
1248
0
    case FRV_OPERAND_U16 :
1249
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U16, (unsigned long *) (& fields->f_u16));
1250
0
      break;
1251
0
    case FRV_OPERAND_U6 :
1252
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U6, (unsigned long *) (& fields->f_u6));
1253
0
      break;
1254
0
    case FRV_OPERAND_UHI16 :
1255
0
      errmsg = parse_uhi16 (cd, strp, FRV_OPERAND_UHI16, (unsigned long *) (& fields->f_u16));
1256
0
      break;
1257
0
    case FRV_OPERAND_ULO16 :
1258
0
      errmsg = parse_ulo16 (cd, strp, FRV_OPERAND_ULO16, (unsigned long *) (& fields->f_u16));
1259
0
      break;
1260
1261
0
    default :
1262
      /* xgettext:c-format */
1263
0
      opcodes_error_handler
1264
0
  (_("internal error: unrecognized field %d while parsing"),
1265
0
   opindex);
1266
0
      abort ();
1267
0
  }
1268
1269
0
  return errmsg;
1270
0
}
1271
1272
cgen_parse_fn * const frv_cgen_parse_handlers[] =
1273
{
1274
  parse_insn_normal,
1275
};
1276
1277
void
1278
frv_cgen_init_asm (CGEN_CPU_DESC cd)
1279
0
{
1280
0
  frv_cgen_init_opcode_table (cd);
1281
0
  frv_cgen_init_ibld_table (cd);
1282
0
  cd->parse_handlers = & frv_cgen_parse_handlers[0];
1283
0
  cd->parse_operand = frv_cgen_parse_operand;
1284
#ifdef CGEN_ASM_INIT_HOOK
1285
CGEN_ASM_INIT_HOOK
1286
#endif
1287
0
}
1288
1289

1290
1291
/* Regex construction routine.
1292
1293
   This translates an opcode syntax string into a regex string,
1294
   by replacing any non-character syntax element (such as an
1295
   opcode) with the pattern '.*'
1296
1297
   It then compiles the regex and stores it in the opcode, for
1298
   later use by frv_cgen_assemble_insn
1299
1300
   Returns NULL for success, an error message for failure.  */
1301
1302
char *
1303
frv_cgen_build_insn_regex (CGEN_INSN *insn)
1304
5.25k
{
1305
5.25k
  CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
1306
5.25k
  const char *mnem = CGEN_INSN_MNEMONIC (insn);
1307
5.25k
  char rxbuf[CGEN_MAX_RX_ELEMENTS];
1308
5.25k
  char *rx = rxbuf;
1309
5.25k
  const CGEN_SYNTAX_CHAR_TYPE *syn;
1310
5.25k
  int reg_err;
1311
1312
5.25k
  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
1313
1314
  /* Mnemonics come first in the syntax string.  */
1315
5.25k
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1316
7
    return _("missing mnemonic in syntax string");
1317
5.25k
  ++syn;
1318
1319
  /* Generate a case sensitive regular expression that emulates case
1320
     insensitive matching in the "C" locale.  We cannot generate a case
1321
     insensitive regular expression because in Turkish locales, 'i' and 'I'
1322
     are not equal modulo case conversion.  */
1323
1324
  /* Copy the literal mnemonic out of the insn.  */
1325
32.3k
  for (; *mnem; mnem++)
1326
27.1k
    {
1327
27.1k
      char c = *mnem;
1328
1329
27.1k
      if (ISALPHA (c))
1330
27.1k
  {
1331
27.1k
    *rx++ = '[';
1332
27.1k
    *rx++ = TOLOWER (c);
1333
27.1k
    *rx++ = TOUPPER (c);
1334
27.1k
    *rx++ = ']';
1335
27.1k
  }
1336
28
      else
1337
28
  *rx++ = c;
1338
27.1k
    }
1339
1340
  /* Copy any remaining literals from the syntax string into the rx.  */
1341
46.0k
  for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
1342
40.8k
    {
1343
40.8k
      if (CGEN_SYNTAX_CHAR_P (* syn))
1344
19.5k
  {
1345
19.5k
    char c = CGEN_SYNTAX_CHAR (* syn);
1346
1347
19.5k
    switch (c)
1348
19.5k
      {
1349
        /* Escape any regex metacharacters in the syntax.  */
1350
0
      case '.': case '[': case '\\':
1351
0
      case '*': case '^': case '$':
1352
1353
#ifdef CGEN_ESCAPE_EXTENDED_REGEX
1354
      case '?': case '{': case '}':
1355
      case '(': case ')': case '*':
1356
      case '|': case '+': case ']':
1357
#endif
1358
0
        *rx++ = '\\';
1359
0
        *rx++ = c;
1360
0
        break;
1361
1362
19.5k
      default:
1363
19.5k
        if (ISALPHA (c))
1364
0
    {
1365
0
      *rx++ = '[';
1366
0
      *rx++ = TOLOWER (c);
1367
0
      *rx++ = TOUPPER (c);
1368
0
      *rx++ = ']';
1369
0
    }
1370
19.5k
        else
1371
19.5k
    *rx++ = c;
1372
19.5k
        break;
1373
19.5k
      }
1374
19.5k
  }
1375
21.3k
      else
1376
21.3k
  {
1377
    /* Replace non-syntax fields with globs.  */
1378
21.3k
    *rx++ = '.';
1379
21.3k
    *rx++ = '*';
1380
21.3k
  }
1381
40.8k
    }
1382
1383
  /* Trailing whitespace ok.  */
1384
5.25k
  * rx++ = '[';
1385
5.25k
  * rx++ = ' ';
1386
5.25k
  * rx++ = '\t';
1387
5.25k
  * rx++ = ']';
1388
5.25k
  * rx++ = '*';
1389
1390
  /* But anchor it after that.  */
1391
5.25k
  * rx++ = '$';
1392
5.25k
  * rx = '\0';
1393
1394
5.25k
  CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
1395
5.25k
  reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
1396
1397
5.25k
  if (reg_err == 0)
1398
5.25k
    return NULL;
1399
0
  else
1400
0
    {
1401
0
      static char msg[80];
1402
1403
0
      regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
1404
0
      regfree ((regex_t *) CGEN_INSN_RX (insn));
1405
0
      free (CGEN_INSN_RX (insn));
1406
0
      (CGEN_INSN_RX (insn)) = NULL;
1407
0
      return msg;
1408
0
    }
1409
5.25k
}
1410
1411

1412
/* Default insn parser.
1413
1414
   The syntax string is scanned and operands are parsed and stored in FIELDS.
1415
   Relocs are queued as we go via other callbacks.
1416
1417
   ??? Note that this is currently an all-or-nothing parser.  If we fail to
1418
   parse the instruction, we return 0 and the caller will start over from
1419
   the beginning.  Backtracking will be necessary in parsing subexpressions,
1420
   but that can be handled there.  Not handling backtracking here may get
1421
   expensive in the case of the m68k.  Deal with later.
1422
1423
   Returns NULL for success, an error message for failure.  */
1424
1425
static const char *
1426
parse_insn_normal (CGEN_CPU_DESC cd,
1427
       const CGEN_INSN *insn,
1428
       const char **strp,
1429
       CGEN_FIELDS *fields)
1430
0
{
1431
  /* ??? Runtime added insns not handled yet.  */
1432
0
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
1433
0
  const char *str = *strp;
1434
0
  const char *errmsg;
1435
0
  const char *p;
1436
0
  const CGEN_SYNTAX_CHAR_TYPE * syn;
1437
0
#ifdef CGEN_MNEMONIC_OPERANDS
1438
  /* FIXME: wip */
1439
0
  int past_opcode_p;
1440
0
#endif
1441
1442
  /* For now we assume the mnemonic is first (there are no leading operands).
1443
     We can parse it without needing to set up operand parsing.
1444
     GAS's input scrubber will ensure mnemonics are lowercase, but we may
1445
     not be called from GAS.  */
1446
0
  p = CGEN_INSN_MNEMONIC (insn);
1447
0
  while (*p && TOLOWER (*p) == TOLOWER (*str))
1448
0
    ++p, ++str;
1449
1450
0
  if (* p)
1451
0
    return _("unrecognized instruction");
1452
1453
#ifndef CGEN_MNEMONIC_OPERANDS
1454
  if (* str && ! ISSPACE (* str))
1455
    return _("unrecognized instruction");
1456
#endif
1457
1458
0
  CGEN_INIT_PARSE (cd);
1459
0
  cgen_init_parse_operand (cd);
1460
0
#ifdef CGEN_MNEMONIC_OPERANDS
1461
0
  past_opcode_p = 0;
1462
0
#endif
1463
1464
  /* We don't check for (*str != '\0') here because we want to parse
1465
     any trailing fake arguments in the syntax string.  */
1466
0
  syn = CGEN_SYNTAX_STRING (syntax);
1467
1468
  /* Mnemonics come first for now, ensure valid string.  */
1469
0
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1470
0
    abort ();
1471
1472
0
  ++syn;
1473
1474
0
  while (* syn != 0)
1475
0
    {
1476
      /* Non operand chars must match exactly.  */
1477
0
      if (CGEN_SYNTAX_CHAR_P (* syn))
1478
0
  {
1479
    /* FIXME: While we allow for non-GAS callers above, we assume the
1480
       first char after the mnemonic part is a space.  */
1481
    /* FIXME: We also take inappropriate advantage of the fact that
1482
       GAS's input scrubber will remove extraneous blanks.  */
1483
0
    if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
1484
0
      {
1485
0
#ifdef CGEN_MNEMONIC_OPERANDS
1486
0
        if (CGEN_SYNTAX_CHAR(* syn) == ' ')
1487
0
    past_opcode_p = 1;
1488
0
#endif
1489
0
        ++ syn;
1490
0
        ++ str;
1491
0
      }
1492
0
    else if (*str)
1493
0
      {
1494
        /* Syntax char didn't match.  Can't be this insn.  */
1495
0
        static char msg [80];
1496
1497
        /* xgettext:c-format */
1498
0
        sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
1499
0
           CGEN_SYNTAX_CHAR(*syn), *str);
1500
0
        return msg;
1501
0
      }
1502
0
    else
1503
0
      {
1504
        /* Ran out of input.  */
1505
0
        static char msg [80];
1506
1507
        /* xgettext:c-format */
1508
0
        sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
1509
0
           CGEN_SYNTAX_CHAR(*syn));
1510
0
        return msg;
1511
0
      }
1512
0
    continue;
1513
0
  }
1514
1515
0
#ifdef CGEN_MNEMONIC_OPERANDS
1516
0
      (void) past_opcode_p;
1517
0
#endif
1518
      /* We have an operand of some sort.  */
1519
0
      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
1520
0
      if (errmsg)
1521
0
  return errmsg;
1522
1523
      /* Done with this operand, continue with next one.  */
1524
0
      ++ syn;
1525
0
    }
1526
1527
  /* If we're at the end of the syntax string, we're done.  */
1528
0
  if (* syn == 0)
1529
0
    {
1530
      /* FIXME: For the moment we assume a valid `str' can only contain
1531
   blanks now.  IE: We needn't try again with a longer version of
1532
   the insn and it is assumed that longer versions of insns appear
1533
   before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
1534
0
      while (ISSPACE (* str))
1535
0
  ++ str;
1536
1537
0
      if (* str != '\0')
1538
0
  return _("junk at end of line"); /* FIXME: would like to include `str' */
1539
1540
0
      return NULL;
1541
0
    }
1542
1543
  /* We couldn't parse it.  */
1544
0
  return _("unrecognized instruction");
1545
0
}
1546

1547
/* Main entry point.
1548
   This routine is called for each instruction to be assembled.
1549
   STR points to the insn to be assembled.
1550
   We assume all necessary tables have been initialized.
1551
   The assembled instruction, less any fixups, is stored in BUF.
1552
   Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
1553
   still needs to be converted to target byte order, otherwise BUF is an array
1554
   of bytes in target byte order.
1555
   The result is a pointer to the insn's entry in the opcode table,
1556
   or NULL if an error occured (an error message will have already been
1557
   printed).
1558
1559
   Note that when processing (non-alias) macro-insns,
1560
   this function recurses.
1561
1562
   ??? It's possible to make this cpu-independent.
1563
   One would have to deal with a few minor things.
1564
   At this point in time doing so would be more of a curiosity than useful
1565
   [for example this file isn't _that_ big], but keeping the possibility in
1566
   mind helps keep the design clean.  */
1567
1568
const CGEN_INSN *
1569
frv_cgen_assemble_insn (CGEN_CPU_DESC cd,
1570
         const char *str,
1571
         CGEN_FIELDS *fields,
1572
         CGEN_INSN_BYTES_PTR buf,
1573
         char **errmsg)
1574
0
{
1575
0
  const char *start;
1576
0
  CGEN_INSN_LIST *ilist;
1577
0
  const char *parse_errmsg = NULL;
1578
0
  const char *insert_errmsg = NULL;
1579
0
  int recognized_mnemonic = 0;
1580
1581
  /* Skip leading white space.  */
1582
0
  while (ISSPACE (* str))
1583
0
    ++ str;
1584
1585
  /* The instructions are stored in hashed lists.
1586
     Get the first in the list.  */
1587
0
  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
1588
1589
  /* Keep looking until we find a match.  */
1590
0
  start = str;
1591
0
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
1592
0
    {
1593
0
      const CGEN_INSN *insn = ilist->insn;
1594
0
      recognized_mnemonic = 1;
1595
1596
#ifdef CGEN_VALIDATE_INSN_SUPPORTED
1597
      /* Not usually needed as unsupported opcodes
1598
   shouldn't be in the hash lists.  */
1599
      /* Is this insn supported by the selected cpu?  */
1600
      if (! frv_cgen_insn_supported (cd, insn))
1601
  continue;
1602
#endif
1603
      /* If the RELAXED attribute is set, this is an insn that shouldn't be
1604
   chosen immediately.  Instead, it is used during assembler/linker
1605
   relaxation if possible.  */
1606
0
      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
1607
0
  continue;
1608
1609
0
      str = start;
1610
1611
      /* Skip this insn if str doesn't look right lexically.  */
1612
0
      if (CGEN_INSN_RX (insn) != NULL &&
1613
0
    regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
1614
0
  continue;
1615
1616
      /* Allow parse/insert handlers to obtain length of insn.  */
1617
0
      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
1618
1619
0
      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
1620
0
      if (parse_errmsg != NULL)
1621
0
  continue;
1622
1623
      /* ??? 0 is passed for `pc'.  */
1624
0
      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
1625
0
             (bfd_vma) 0);
1626
0
      if (insert_errmsg != NULL)
1627
0
        continue;
1628
1629
      /* It is up to the caller to actually output the insn and any
1630
         queued relocs.  */
1631
0
      return insn;
1632
0
    }
1633
1634
0
  {
1635
0
    static char errbuf[150];
1636
0
    const char *tmp_errmsg;
1637
0
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
1638
0
#define be_verbose 1
1639
#else
1640
#define be_verbose 0
1641
#endif
1642
1643
0
    if (be_verbose)
1644
0
      {
1645
  /* If requesting verbose error messages, use insert_errmsg.
1646
     Failing that, use parse_errmsg.  */
1647
0
  tmp_errmsg = (insert_errmsg ? insert_errmsg :
1648
0
          parse_errmsg ? parse_errmsg :
1649
0
          recognized_mnemonic ?
1650
0
          _("unrecognized form of instruction") :
1651
0
          _("unrecognized instruction"));
1652
1653
0
  if (strlen (start) > 50)
1654
    /* xgettext:c-format */
1655
0
    sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1656
0
  else
1657
    /* xgettext:c-format */
1658
0
    sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
1659
0
      }
1660
0
    else
1661
0
      {
1662
0
  if (strlen (start) > 50)
1663
    /* xgettext:c-format */
1664
0
    sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1665
0
  else
1666
    /* xgettext:c-format */
1667
0
    sprintf (errbuf, _("bad instruction `%.50s'"), start);
1668
0
      }
1669
1670
0
    *errmsg = errbuf;
1671
0
    return NULL;
1672
0
  }
1673
0
}