Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/opcodes/fr30-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 "fr30-desc.h"
36
#include "fr30-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
/* Handle register lists for LDMx and STMx.  */
54
55
static int
56
parse_register_number (const char **strp)
57
0
{
58
0
  int regno;
59
60
0
  if (**strp < '0' || **strp > '9')
61
0
    return -1; /* Error.  */
62
0
  regno = **strp - '0';
63
0
  ++*strp;
64
65
0
  if (**strp >= '0' && **strp <= '9')
66
0
    {
67
0
      regno = regno * 10 + (**strp - '0');
68
0
      ++*strp;
69
0
    }
70
71
0
  return regno;
72
0
}
73
74
static const char *
75
parse_register_list (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
76
         const char **strp,
77
         int opindex ATTRIBUTE_UNUSED,
78
         unsigned long *valuep,
79
         int high_low,   /* 0 == high, 1 == low.  */
80
         int load_store) /* 0 == load, 1 == store.  */
81
0
{
82
0
  *valuep = 0;
83
0
  while (**strp && **strp != ')')
84
0
    {
85
0
      int regno;
86
87
0
      if (**strp != 'R' && **strp != 'r')
88
0
  break;
89
0
      ++*strp;
90
91
0
      regno = parse_register_number (strp);
92
0
      if (regno == -1)
93
0
  return _("Register number is not valid");
94
0
      if (regno > 7 && !high_low)
95
0
  return _("Register must be between r0 and r7");
96
0
      if (regno < 8 && high_low)
97
0
  return _("Register must be between r8 and r15");
98
99
0
      if (high_low)
100
0
  regno -= 8;
101
102
0
      if (load_store) /* Mask is reversed for store.  */
103
0
  *valuep |= 0x80 >> regno;
104
0
      else
105
0
  *valuep |= 1 << regno;
106
107
0
      if (**strp == ',')
108
0
  {
109
0
    if (*(*strp + 1) == ')')
110
0
      break;
111
0
    ++*strp;
112
0
  }
113
0
    }
114
115
0
  if (!*strp || **strp != ')')
116
0
    return _("Register list is not valid");
117
118
0
  return NULL;
119
0
}
120
121
static const char *
122
parse_low_register_list_ld (CGEN_CPU_DESC cd,
123
          const char **strp,
124
          int opindex,
125
          unsigned long *valuep)
126
0
{
127
0
  return parse_register_list (cd, strp, opindex, valuep,
128
0
            0 /* Low.  */, 0 /* Load.  */);
129
0
}
130
131
static const char *
132
parse_hi_register_list_ld (CGEN_CPU_DESC cd,
133
         const char **strp,
134
         int opindex,
135
         unsigned long *valuep)
136
0
{
137
0
  return parse_register_list (cd, strp, opindex, valuep,
138
0
            1 /* High.  */, 0 /* Load.  */);
139
0
}
140
141
static const char *
142
parse_low_register_list_st (CGEN_CPU_DESC cd,
143
          const char **strp,
144
          int opindex,
145
          unsigned long *valuep)
146
0
{
147
0
  return parse_register_list (cd, strp, opindex, valuep,
148
0
            0 /* Low.  */, 1 /* Store.  */);
149
0
}
150
151
static const char *
152
parse_hi_register_list_st (CGEN_CPU_DESC cd,
153
         const char **strp,
154
         int opindex,
155
         unsigned long *valuep)
156
0
{
157
0
  return parse_register_list (cd, strp, opindex, valuep,
158
0
            1 /* High.  */, 1 /* Store.  */);
159
0
}
160
161
/* -- */
162
163
const char * fr30_cgen_parse_operand
164
  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
165
166
/* Main entry point for operand parsing.
167
168
   This function is basically just a big switch statement.  Earlier versions
169
   used tables to look up the function to use, but
170
   - if the table contains both assembler and disassembler functions then
171
     the disassembler contains much of the assembler and vice-versa,
172
   - there's a lot of inlining possibilities as things grow,
173
   - using a switch statement avoids the function call overhead.
174
175
   This function could be moved into `parse_insn_normal', but keeping it
176
   separate makes clear the interface between `parse_insn_normal' and each of
177
   the handlers.  */
178
179
const char *
180
fr30_cgen_parse_operand (CGEN_CPU_DESC cd,
181
         int opindex,
182
         const char ** strp,
183
         CGEN_FIELDS * fields)
184
0
{
185
0
  const char * errmsg = NULL;
186
  /* Used by scalar operands that still need to be parsed.  */
187
0
  long junk ATTRIBUTE_UNUSED;
188
189
0
  switch (opindex)
190
0
    {
191
0
    case FR30_OPERAND_CRI :
192
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRi);
193
0
      break;
194
0
    case FR30_OPERAND_CRJ :
195
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRj);
196
0
      break;
197
0
    case FR30_OPERAND_R13 :
198
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r13, & junk);
199
0
      break;
200
0
    case FR30_OPERAND_R14 :
201
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r14, & junk);
202
0
      break;
203
0
    case FR30_OPERAND_R15 :
204
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r15, & junk);
205
0
      break;
206
0
    case FR30_OPERAND_RI :
207
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ri);
208
0
      break;
209
0
    case FR30_OPERAND_RIC :
210
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ric);
211
0
      break;
212
0
    case FR30_OPERAND_RJ :
213
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rj);
214
0
      break;
215
0
    case FR30_OPERAND_RJC :
216
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rjc);
217
0
      break;
218
0
    case FR30_OPERAND_RS1 :
219
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs1);
220
0
      break;
221
0
    case FR30_OPERAND_RS2 :
222
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs2);
223
0
      break;
224
0
    case FR30_OPERAND_CC :
225
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CC, (unsigned long *) (& fields->f_cc));
226
0
      break;
227
0
    case FR30_OPERAND_CCC :
228
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CCC, (unsigned long *) (& fields->f_ccc));
229
0
      break;
230
0
    case FR30_OPERAND_DIR10 :
231
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR10, (unsigned long *) (& fields->f_dir10));
232
0
      break;
233
0
    case FR30_OPERAND_DIR8 :
234
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR8, (unsigned long *) (& fields->f_dir8));
235
0
      break;
236
0
    case FR30_OPERAND_DIR9 :
237
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR9, (unsigned long *) (& fields->f_dir9));
238
0
      break;
239
0
    case FR30_OPERAND_DISP10 :
240
0
      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP10, (long *) (& fields->f_disp10));
241
0
      break;
242
0
    case FR30_OPERAND_DISP8 :
243
0
      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP8, (long *) (& fields->f_disp8));
244
0
      break;
245
0
    case FR30_OPERAND_DISP9 :
246
0
      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP9, (long *) (& fields->f_disp9));
247
0
      break;
248
0
    case FR30_OPERAND_I20 :
249
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I20, (unsigned long *) (& fields->f_i20));
250
0
      break;
251
0
    case FR30_OPERAND_I32 :
252
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I32, (unsigned long *) (& fields->f_i32));
253
0
      break;
254
0
    case FR30_OPERAND_I8 :
255
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I8, (unsigned long *) (& fields->f_i8));
256
0
      break;
257
0
    case FR30_OPERAND_LABEL12 :
258
0
      {
259
0
        bfd_vma value = 0;
260
0
        errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL12, 0, NULL,  & value);
261
0
        fields->f_rel12 = value;
262
0
      }
263
0
      break;
264
0
    case FR30_OPERAND_LABEL9 :
265
0
      {
266
0
        bfd_vma value = 0;
267
0
        errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
268
0
        fields->f_rel9 = value;
269
0
      }
270
0
      break;
271
0
    case FR30_OPERAND_M4 :
272
0
      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_M4, (long *) (& fields->f_m4));
273
0
      break;
274
0
    case FR30_OPERAND_PS :
275
0
      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_ps, & junk);
276
0
      break;
277
0
    case FR30_OPERAND_REGLIST_HI_LD :
278
0
      errmsg = parse_hi_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_HI_LD, (unsigned long *) (& fields->f_reglist_hi_ld));
279
0
      break;
280
0
    case FR30_OPERAND_REGLIST_HI_ST :
281
0
      errmsg = parse_hi_register_list_st (cd, strp, FR30_OPERAND_REGLIST_HI_ST, (unsigned long *) (& fields->f_reglist_hi_st));
282
0
      break;
283
0
    case FR30_OPERAND_REGLIST_LOW_LD :
284
0
      errmsg = parse_low_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_LOW_LD, (unsigned long *) (& fields->f_reglist_low_ld));
285
0
      break;
286
0
    case FR30_OPERAND_REGLIST_LOW_ST :
287
0
      errmsg = parse_low_register_list_st (cd, strp, FR30_OPERAND_REGLIST_LOW_ST, (unsigned long *) (& fields->f_reglist_low_st));
288
0
      break;
289
0
    case FR30_OPERAND_S10 :
290
0
      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_S10, (long *) (& fields->f_s10));
291
0
      break;
292
0
    case FR30_OPERAND_U10 :
293
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U10, (unsigned long *) (& fields->f_u10));
294
0
      break;
295
0
    case FR30_OPERAND_U4 :
296
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4, (unsigned long *) (& fields->f_u4));
297
0
      break;
298
0
    case FR30_OPERAND_U4C :
299
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4C, (unsigned long *) (& fields->f_u4c));
300
0
      break;
301
0
    case FR30_OPERAND_U8 :
302
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U8, (unsigned long *) (& fields->f_u8));
303
0
      break;
304
0
    case FR30_OPERAND_UDISP6 :
305
0
      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_UDISP6, (unsigned long *) (& fields->f_udisp6));
306
0
      break;
307
308
0
    default :
309
      /* xgettext:c-format */
310
0
      opcodes_error_handler
311
0
  (_("internal error: unrecognized field %d while parsing"),
312
0
   opindex);
313
0
      abort ();
314
0
  }
315
316
0
  return errmsg;
317
0
}
318
319
cgen_parse_fn * const fr30_cgen_parse_handlers[] =
320
{
321
  parse_insn_normal,
322
};
323
324
void
325
fr30_cgen_init_asm (CGEN_CPU_DESC cd)
326
0
{
327
0
  fr30_cgen_init_opcode_table (cd);
328
0
  fr30_cgen_init_ibld_table (cd);
329
0
  cd->parse_handlers = & fr30_cgen_parse_handlers[0];
330
0
  cd->parse_operand = fr30_cgen_parse_operand;
331
#ifdef CGEN_ASM_INIT_HOOK
332
CGEN_ASM_INIT_HOOK
333
#endif
334
0
}
335
336

337
338
/* Regex construction routine.
339
340
   This translates an opcode syntax string into a regex string,
341
   by replacing any non-character syntax element (such as an
342
   opcode) with the pattern '.*'
343
344
   It then compiles the regex and stores it in the opcode, for
345
   later use by fr30_cgen_assemble_insn
346
347
   Returns NULL for success, an error message for failure.  */
348
349
char *
350
fr30_cgen_build_insn_regex (CGEN_INSN *insn)
351
507
{
352
507
  CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
353
507
  const char *mnem = CGEN_INSN_MNEMONIC (insn);
354
507
  char rxbuf[CGEN_MAX_RX_ELEMENTS];
355
507
  char *rx = rxbuf;
356
507
  const CGEN_SYNTAX_CHAR_TYPE *syn;
357
507
  int reg_err;
358
359
507
  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
360
361
  /* Mnemonics come first in the syntax string.  */
362
507
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
363
3
    return _("missing mnemonic in syntax string");
364
504
  ++syn;
365
366
  /* Generate a case sensitive regular expression that emulates case
367
     insensitive matching in the "C" locale.  We cannot generate a case
368
     insensitive regular expression because in Turkish locales, 'i' and 'I'
369
     are not equal modulo case conversion.  */
370
371
  /* Copy the literal mnemonic out of the insn.  */
372
2.44k
  for (; *mnem; mnem++)
373
1.94k
    {
374
1.94k
      char c = *mnem;
375
376
1.94k
      if (ISALPHA (c))
377
1.79k
  {
378
1.79k
    *rx++ = '[';
379
1.79k
    *rx++ = TOLOWER (c);
380
1.79k
    *rx++ = TOUPPER (c);
381
1.79k
    *rx++ = ']';
382
1.79k
  }
383
147
      else
384
147
  *rx++ = c;
385
1.94k
    }
386
387
  /* Copy any remaining literals from the syntax string into the rx.  */
388
2.59k
  for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
389
2.08k
    {
390
2.08k
      if (CGEN_SYNTAX_CHAR_P (* syn))
391
1.23k
  {
392
1.23k
    char c = CGEN_SYNTAX_CHAR (* syn);
393
394
1.23k
    switch (c)
395
1.23k
      {
396
        /* Escape any regex metacharacters in the syntax.  */
397
0
      case '.': case '[': case '\\':
398
0
      case '*': case '^': case '$':
399
400
#ifdef CGEN_ESCAPE_EXTENDED_REGEX
401
      case '?': case '{': case '}':
402
      case '(': case ')': case '*':
403
      case '|': case '+': case ']':
404
#endif
405
0
        *rx++ = '\\';
406
0
        *rx++ = c;
407
0
        break;
408
409
1.23k
      default:
410
1.23k
        if (ISALPHA (c))
411
0
    {
412
0
      *rx++ = '[';
413
0
      *rx++ = TOLOWER (c);
414
0
      *rx++ = TOUPPER (c);
415
0
      *rx++ = ']';
416
0
    }
417
1.23k
        else
418
1.23k
    *rx++ = c;
419
1.23k
        break;
420
1.23k
      }
421
1.23k
  }
422
858
      else
423
858
  {
424
    /* Replace non-syntax fields with globs.  */
425
858
    *rx++ = '.';
426
858
    *rx++ = '*';
427
858
  }
428
2.08k
    }
429
430
  /* Trailing whitespace ok.  */
431
504
  * rx++ = '[';
432
504
  * rx++ = ' ';
433
504
  * rx++ = '\t';
434
504
  * rx++ = ']';
435
504
  * rx++ = '*';
436
437
  /* But anchor it after that.  */
438
504
  * rx++ = '$';
439
504
  * rx = '\0';
440
441
504
  CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
442
504
  reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
443
444
504
  if (reg_err == 0)
445
504
    return NULL;
446
0
  else
447
0
    {
448
0
      static char msg[80];
449
450
0
      regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
451
0
      regfree ((regex_t *) CGEN_INSN_RX (insn));
452
0
      free (CGEN_INSN_RX (insn));
453
0
      (CGEN_INSN_RX (insn)) = NULL;
454
0
      return msg;
455
0
    }
456
504
}
457
458

459
/* Default insn parser.
460
461
   The syntax string is scanned and operands are parsed and stored in FIELDS.
462
   Relocs are queued as we go via other callbacks.
463
464
   ??? Note that this is currently an all-or-nothing parser.  If we fail to
465
   parse the instruction, we return 0 and the caller will start over from
466
   the beginning.  Backtracking will be necessary in parsing subexpressions,
467
   but that can be handled there.  Not handling backtracking here may get
468
   expensive in the case of the m68k.  Deal with later.
469
470
   Returns NULL for success, an error message for failure.  */
471
472
static const char *
473
parse_insn_normal (CGEN_CPU_DESC cd,
474
       const CGEN_INSN *insn,
475
       const char **strp,
476
       CGEN_FIELDS *fields)
477
0
{
478
  /* ??? Runtime added insns not handled yet.  */
479
0
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
480
0
  const char *str = *strp;
481
0
  const char *errmsg;
482
0
  const char *p;
483
0
  const CGEN_SYNTAX_CHAR_TYPE * syn;
484
0
#ifdef CGEN_MNEMONIC_OPERANDS
485
  /* FIXME: wip */
486
0
  int past_opcode_p;
487
0
#endif
488
489
  /* For now we assume the mnemonic is first (there are no leading operands).
490
     We can parse it without needing to set up operand parsing.
491
     GAS's input scrubber will ensure mnemonics are lowercase, but we may
492
     not be called from GAS.  */
493
0
  p = CGEN_INSN_MNEMONIC (insn);
494
0
  while (*p && TOLOWER (*p) == TOLOWER (*str))
495
0
    ++p, ++str;
496
497
0
  if (* p)
498
0
    return _("unrecognized instruction");
499
500
#ifndef CGEN_MNEMONIC_OPERANDS
501
  if (* str && ! ISSPACE (* str))
502
    return _("unrecognized instruction");
503
#endif
504
505
0
  CGEN_INIT_PARSE (cd);
506
0
  cgen_init_parse_operand (cd);
507
0
#ifdef CGEN_MNEMONIC_OPERANDS
508
0
  past_opcode_p = 0;
509
0
#endif
510
511
  /* We don't check for (*str != '\0') here because we want to parse
512
     any trailing fake arguments in the syntax string.  */
513
0
  syn = CGEN_SYNTAX_STRING (syntax);
514
515
  /* Mnemonics come first for now, ensure valid string.  */
516
0
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
517
0
    abort ();
518
519
0
  ++syn;
520
521
0
  while (* syn != 0)
522
0
    {
523
      /* Non operand chars must match exactly.  */
524
0
      if (CGEN_SYNTAX_CHAR_P (* syn))
525
0
  {
526
    /* FIXME: While we allow for non-GAS callers above, we assume the
527
       first char after the mnemonic part is a space.  */
528
    /* FIXME: We also take inappropriate advantage of the fact that
529
       GAS's input scrubber will remove extraneous blanks.  */
530
0
    if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
531
0
      {
532
0
#ifdef CGEN_MNEMONIC_OPERANDS
533
0
        if (CGEN_SYNTAX_CHAR(* syn) == ' ')
534
0
    past_opcode_p = 1;
535
0
#endif
536
0
        ++ syn;
537
0
        ++ str;
538
0
      }
539
0
    else if (*str)
540
0
      {
541
        /* Syntax char didn't match.  Can't be this insn.  */
542
0
        static char msg [80];
543
544
        /* xgettext:c-format */
545
0
        sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
546
0
           CGEN_SYNTAX_CHAR(*syn), *str);
547
0
        return msg;
548
0
      }
549
0
    else
550
0
      {
551
        /* Ran out of input.  */
552
0
        static char msg [80];
553
554
        /* xgettext:c-format */
555
0
        sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
556
0
           CGEN_SYNTAX_CHAR(*syn));
557
0
        return msg;
558
0
      }
559
0
    continue;
560
0
  }
561
562
0
#ifdef CGEN_MNEMONIC_OPERANDS
563
0
      (void) past_opcode_p;
564
0
#endif
565
      /* We have an operand of some sort.  */
566
0
      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
567
0
      if (errmsg)
568
0
  return errmsg;
569
570
      /* Done with this operand, continue with next one.  */
571
0
      ++ syn;
572
0
    }
573
574
  /* If we're at the end of the syntax string, we're done.  */
575
0
  if (* syn == 0)
576
0
    {
577
      /* FIXME: For the moment we assume a valid `str' can only contain
578
   blanks now.  IE: We needn't try again with a longer version of
579
   the insn and it is assumed that longer versions of insns appear
580
   before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
581
0
      while (ISSPACE (* str))
582
0
  ++ str;
583
584
0
      if (* str != '\0')
585
0
  return _("junk at end of line"); /* FIXME: would like to include `str' */
586
587
0
      return NULL;
588
0
    }
589
590
  /* We couldn't parse it.  */
591
0
  return _("unrecognized instruction");
592
0
}
593

594
/* Main entry point.
595
   This routine is called for each instruction to be assembled.
596
   STR points to the insn to be assembled.
597
   We assume all necessary tables have been initialized.
598
   The assembled instruction, less any fixups, is stored in BUF.
599
   Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
600
   still needs to be converted to target byte order, otherwise BUF is an array
601
   of bytes in target byte order.
602
   The result is a pointer to the insn's entry in the opcode table,
603
   or NULL if an error occured (an error message will have already been
604
   printed).
605
606
   Note that when processing (non-alias) macro-insns,
607
   this function recurses.
608
609
   ??? It's possible to make this cpu-independent.
610
   One would have to deal with a few minor things.
611
   At this point in time doing so would be more of a curiosity than useful
612
   [for example this file isn't _that_ big], but keeping the possibility in
613
   mind helps keep the design clean.  */
614
615
const CGEN_INSN *
616
fr30_cgen_assemble_insn (CGEN_CPU_DESC cd,
617
         const char *str,
618
         CGEN_FIELDS *fields,
619
         CGEN_INSN_BYTES_PTR buf,
620
         char **errmsg)
621
0
{
622
0
  const char *start;
623
0
  CGEN_INSN_LIST *ilist;
624
0
  const char *parse_errmsg = NULL;
625
0
  const char *insert_errmsg = NULL;
626
0
  int recognized_mnemonic = 0;
627
628
  /* Skip leading white space.  */
629
0
  while (ISSPACE (* str))
630
0
    ++ str;
631
632
  /* The instructions are stored in hashed lists.
633
     Get the first in the list.  */
634
0
  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
635
636
  /* Keep looking until we find a match.  */
637
0
  start = str;
638
0
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
639
0
    {
640
0
      const CGEN_INSN *insn = ilist->insn;
641
0
      recognized_mnemonic = 1;
642
643
#ifdef CGEN_VALIDATE_INSN_SUPPORTED
644
      /* Not usually needed as unsupported opcodes
645
   shouldn't be in the hash lists.  */
646
      /* Is this insn supported by the selected cpu?  */
647
      if (! fr30_cgen_insn_supported (cd, insn))
648
  continue;
649
#endif
650
      /* If the RELAXED attribute is set, this is an insn that shouldn't be
651
   chosen immediately.  Instead, it is used during assembler/linker
652
   relaxation if possible.  */
653
0
      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
654
0
  continue;
655
656
0
      str = start;
657
658
      /* Skip this insn if str doesn't look right lexically.  */
659
0
      if (CGEN_INSN_RX (insn) != NULL &&
660
0
    regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
661
0
  continue;
662
663
      /* Allow parse/insert handlers to obtain length of insn.  */
664
0
      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
665
666
0
      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
667
0
      if (parse_errmsg != NULL)
668
0
  continue;
669
670
      /* ??? 0 is passed for `pc'.  */
671
0
      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
672
0
             (bfd_vma) 0);
673
0
      if (insert_errmsg != NULL)
674
0
        continue;
675
676
      /* It is up to the caller to actually output the insn and any
677
         queued relocs.  */
678
0
      return insn;
679
0
    }
680
681
0
  {
682
0
    static char errbuf[150];
683
0
    const char *tmp_errmsg;
684
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
685
#define be_verbose 1
686
#else
687
0
#define be_verbose 0
688
0
#endif
689
690
0
    if (be_verbose)
691
0
      {
692
  /* If requesting verbose error messages, use insert_errmsg.
693
     Failing that, use parse_errmsg.  */
694
0
  tmp_errmsg = (insert_errmsg ? insert_errmsg :
695
0
          parse_errmsg ? parse_errmsg :
696
0
          recognized_mnemonic ?
697
0
          _("unrecognized form of instruction") :
698
0
          _("unrecognized instruction"));
699
700
0
  if (strlen (start) > 50)
701
    /* xgettext:c-format */
702
0
    sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
703
0
  else
704
    /* xgettext:c-format */
705
0
    sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
706
0
      }
707
0
    else
708
0
      {
709
0
  if (strlen (start) > 50)
710
    /* xgettext:c-format */
711
0
    sprintf (errbuf, _("bad instruction `%.50s...'"), start);
712
0
  else
713
    /* xgettext:c-format */
714
0
    sprintf (errbuf, _("bad instruction `%.50s'"), start);
715
0
      }
716
717
0
    *errmsg = errbuf;
718
0
    return NULL;
719
0
  }
720
0
}