OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [opcodes/] [epiphany-asm.c] - Blame information for rev 163

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 163 khays
/* Assembler interface for targets using CGEN. -*- C -*-
2
   CGEN: Cpu tools GENerator
3
 
4
   THIS FILE IS MACHINE GENERATED WITH CGEN.
5
   - the resultant file is machine generated, cgen-asm.in isn't
6
 
7
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005, 2007, 2008, 2010
8
   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 "epiphany-desc.h"
36
#include "epiphany-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
const char *
54
parse_shortregs (CGEN_CPU_DESC cd,
55
                 const char ** strp,
56
                 CGEN_KEYWORD * keywords,
57
                 long * regno)
58
{
59
  const char * errmsg;
60
 
61
  /* Parse register.  */
62
  errmsg = cgen_parse_keyword (cd, strp, keywords, regno);
63
 
64
  if (errmsg)
65
    return errmsg;
66
 
67
  if (*regno > 7)
68
    errmsg = _("register unavailable for short instructions");
69
 
70
  return errmsg;
71
}
72
 
73
static const char * parse_simm_not_reg (CGEN_CPU_DESC, const char **, int,
74
                                        long *);
75
 
76
static const char *
77
parse_uimm_not_reg (CGEN_CPU_DESC cd,
78
                    const char ** strp,
79
                    int opindex,
80
                    unsigned long * valuep)
81
{
82
  long * svalp = (void *) valuep;
83
  return parse_simm_not_reg (cd, strp, opindex, svalp);
84
}
85
 
86
/* Handle simm3/simm11/imm3/imm12.  */
87
 
88
static const char *
89
parse_simm_not_reg (CGEN_CPU_DESC cd,
90
                   const char ** strp,
91
                   int opindex,
92
                   long * valuep)
93
{
94
  const char * errmsg;
95
 
96
  int   sign = 0;
97
  int   bits = 0;
98
 
99
  switch (opindex)
100
    {
101
    case EPIPHANY_OPERAND_SIMM3:
102
      sign = 1; bits = 3; break;
103
    case EPIPHANY_OPERAND_SIMM11:
104
      sign = 1; bits = 11; break;
105
    case EPIPHANY_OPERAND_DISP3:
106
      sign = 0; bits = 3; break;
107
    case EPIPHANY_OPERAND_DISP11:
108
      /* Load/store displacement is a sign-magnitude 12 bit value.  */
109
      sign = 0; bits = 11; break;
110
    }
111
 
112
  /* First try to parse as a register name and reject the operand.  */
113
  errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names,valuep);
114
  if (!errmsg)
115
    return _("register name used as immediate value");
116
 
117
  errmsg = (sign ? cgen_parse_signed_integer (cd, strp, opindex, valuep)
118
            : cgen_parse_unsigned_integer (cd, strp, opindex,
119
                                          (unsigned long *) valuep));
120
  if (errmsg)
121
    return errmsg;
122
 
123
  if (sign)
124
    errmsg = cgen_validate_signed_integer (*valuep,
125
                                          -((1L << bits) - 1), (1 << (bits - 1)) - 1);
126
  else
127
    errmsg = cgen_validate_unsigned_integer (*valuep, 0, (1L << bits) - 1);
128
 
129
  return errmsg;
130
}
131
 
132
static const char *
133
parse_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
134
                 const char ** strp,
135
                 int opindex ATTRIBUTE_UNUSED,
136
                 unsigned long *valuep)
137
{
138
  if (**strp == '#')
139
    ++*strp;                    /* Skip leading hashes.  */
140
 
141
  if (**strp == '-')
142
    {
143
      *valuep = 1;
144
      ++*strp;
145
    }
146
  else if (**strp == '+')
147
    {
148
      *valuep = 0;
149
      ++*strp;
150
    }
151
  else
152
    *valuep = 0;
153
 
154
  return NULL;
155
}
156
 
157
static const char *
158
parse_imm8 (CGEN_CPU_DESC cd,
159
            const char ** strp,
160
            int opindex,
161
            bfd_reloc_code_real_type code,
162
            enum cgen_parse_operand_result * result_type,
163
            bfd_vma * valuep)
164
{
165
  const char * errmsg;
166
  enum cgen_parse_operand_result rt;
167
  long dummyval;
168
 
169
  if (!result_type)
170
    result_type = &rt;
171
 
172
  code = BFD_RELOC_NONE;
173
 
174
  if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names, &dummyval)
175
      || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
176
                              &dummyval))
177
    /* Don't treat "mov ip,ip" as a move-immediate.  */
178
    return _("register source in immediate move");
179
 
180
  errmsg = cgen_parse_address (cd, strp, opindex, code, result_type, valuep);
181
  if (errmsg)
182
    return errmsg;
183
 
184
  if (*result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
185
    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xff);
186
  else
187
    errmsg = _("byte relocation unsupported");
188
 
189
  *valuep &= 0xff;
190
  return errmsg;
191
}
192
 
193
static const char * MISSING_CLOSE_PARENTHESIS = N_("missing `)'");
194
 
195
static const char *
196
parse_imm16 (CGEN_CPU_DESC cd,
197
             const char ** strp,
198
             int opindex,
199
             bfd_reloc_code_real_type code ATTRIBUTE_UNUSED,
200
             enum cgen_parse_operand_result * result_type,
201
             bfd_vma * valuep)
202
{
203
  const char * errmsg;
204
  enum cgen_parse_operand_result rt;
205
  long dummyval;
206
 
207
  if (!result_type)
208
    result_type = &rt;
209
 
210
  if (strncasecmp (*strp, "%high(", 6) == 0)
211
    {
212
      *strp += 6;
213
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_HIGH,
214
                                   result_type, valuep);
215
      if (**strp != ')')
216
        return MISSING_CLOSE_PARENTHESIS;
217
      ++*strp;
218
      *valuep >>= 16;
219
    }
220
  else if (strncasecmp (*strp, "%low(", 5) == 0)
221
    {
222
      *strp += 5;
223
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_LOW,
224
                                   result_type, valuep);
225
      if (**strp != ')')
226
        return MISSING_CLOSE_PARENTHESIS;
227
      ++*strp;
228
    }
229
  else if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names,
230
                                &dummyval)
231
           || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
232
                                   &dummyval))
233
    /* Don't treat "mov ip,ip" as a move-immediate.  */
234
    return _("register source in immediate move");
235
  else
236
    errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
237
                                 result_type, valuep);
238
 
239
  if (!errmsg && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
240
    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xffff);
241
 
242
  *valuep &= 0xffff;
243
  return errmsg;
244
}
245
 
246
const char *
247
parse_branch_addr (CGEN_CPU_DESC cd,
248
                   const char ** strp,
249
                   int opindex,
250
                   int opinfo ATTRIBUTE_UNUSED,
251
                   enum cgen_parse_operand_result * resultp ATTRIBUTE_UNUSED,
252
                   bfd_vma *valuep ATTRIBUTE_UNUSED)
253
{
254
  const char * errmsg;
255
  enum cgen_parse_operand_result result_type;
256
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
257
  bfd_vma value;
258
 
259
  switch (opindex)
260
    {
261
    case EPIPHANY_OPERAND_SIMM24:
262
      code = BFD_RELOC_EPIPHANY_SIMM24;
263
      break;
264
 
265
    case EPIPHANY_OPERAND_SIMM8:
266
      code = BFD_RELOC_EPIPHANY_SIMM8;
267
      break;
268
 
269
    default:
270
      errmsg = _("ABORT: unknown operand");
271
      return errmsg;
272
    }
273
 
274
  errmsg = cgen_parse_address (cd, strp, opindex, code,
275
                               &result_type, &value);
276
  if (errmsg == NULL)
277
    {
278
      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
279
        {
280
          /* Act as if we had done a PC-relative branch, ala .+num.  */
281
          char buf[20];
282
          const char * bufp = (const char *) buf;
283
 
284
          sprintf (buf, ".+%ld", (long) value);
285
          errmsg = cgen_parse_address (cd, &bufp, opindex, code, &result_type,
286
                                       &value);
287
        }
288
 
289
      if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
290
        {
291
          /* This will happen for things like (s2-s1) where s2 and s1
292
             are labels.  */
293
          /* Nothing further to be done.  */
294
        }
295
      else
296
        errmsg = _("Not a pc-relative address.");
297
    }
298
  return errmsg;
299
}
300
 
301
/* -- dis.c */
302
 
303
const char * epiphany_cgen_parse_operand
304
  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
305
 
306
/* Main entry point for operand parsing.
307
 
308
   This function is basically just a big switch statement.  Earlier versions
309
   used tables to look up the function to use, but
310
   - if the table contains both assembler and disassembler functions then
311
     the disassembler contains much of the assembler and vice-versa,
312
   - there's a lot of inlining possibilities as things grow,
313
   - using a switch statement avoids the function call overhead.
314
 
315
   This function could be moved into `parse_insn_normal', but keeping it
316
   separate makes clear the interface between `parse_insn_normal' and each of
317
   the handlers.  */
318
 
319
const char *
320
epiphany_cgen_parse_operand (CGEN_CPU_DESC cd,
321
                           int opindex,
322
                           const char ** strp,
323
                           CGEN_FIELDS * fields)
324
{
325
  const char * errmsg = NULL;
326
  /* Used by scalar operands that still need to be parsed.  */
327
  long junk ATTRIBUTE_UNUSED;
328
 
329
  switch (opindex)
330
    {
331
    case EPIPHANY_OPERAND_DIRECTION :
332
      errmsg = parse_postindex (cd, strp, EPIPHANY_OPERAND_DIRECTION, (unsigned long *) (& fields->f_addsubx));
333
      break;
334
    case EPIPHANY_OPERAND_DISP11 :
335
      errmsg = parse_uimm_not_reg (cd, strp, EPIPHANY_OPERAND_DISP11, (unsigned long *) (& fields->f_disp11));
336
      break;
337
    case EPIPHANY_OPERAND_DISP3 :
338
      errmsg = cgen_parse_unsigned_integer (cd, strp, EPIPHANY_OPERAND_DISP3, (unsigned long *) (& fields->f_disp3));
339
      break;
340
    case EPIPHANY_OPERAND_DPMI :
341
      errmsg = parse_postindex (cd, strp, EPIPHANY_OPERAND_DPMI, (unsigned long *) (& fields->f_subd));
342
      break;
343
    case EPIPHANY_OPERAND_FRD :
344
      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd);
345
      break;
346
    case EPIPHANY_OPERAND_FRD6 :
347
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd6);
348
      break;
349
    case EPIPHANY_OPERAND_FRM :
350
      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm);
351
      break;
352
    case EPIPHANY_OPERAND_FRM6 :
353
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm6);
354
      break;
355
    case EPIPHANY_OPERAND_FRN :
356
      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn);
357
      break;
358
    case EPIPHANY_OPERAND_FRN6 :
359
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn6);
360
      break;
361
    case EPIPHANY_OPERAND_IMM16 :
362
      {
363
        bfd_vma value = 0;
364
        errmsg = parse_imm16 (cd, strp, EPIPHANY_OPERAND_IMM16, 0, NULL,  & value);
365
        fields->f_imm16 = value;
366
      }
367
      break;
368
    case EPIPHANY_OPERAND_IMM8 :
369
      {
370
        bfd_vma value = 0;
371
        errmsg = parse_imm8 (cd, strp, EPIPHANY_OPERAND_IMM8, 0, NULL,  & value);
372
        fields->f_imm8 = value;
373
      }
374
      break;
375
    case EPIPHANY_OPERAND_RD :
376
      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd);
377
      break;
378
    case EPIPHANY_OPERAND_RD6 :
379
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd6);
380
      break;
381
    case EPIPHANY_OPERAND_RM :
382
      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm);
383
      break;
384
    case EPIPHANY_OPERAND_RM6 :
385
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm6);
386
      break;
387
    case EPIPHANY_OPERAND_RN :
388
      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn);
389
      break;
390
    case EPIPHANY_OPERAND_RN6 :
391
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn6);
392
      break;
393
    case EPIPHANY_OPERAND_SD :
394
      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sd);
395
      break;
396
    case EPIPHANY_OPERAND_SD6 :
397
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sd6);
398
      break;
399
    case EPIPHANY_OPERAND_SDDMA :
400
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crdma_names, & fields->f_sd6);
401
      break;
402
    case EPIPHANY_OPERAND_SDMEM :
403
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmem_names, & fields->f_sd6);
404
      break;
405
    case EPIPHANY_OPERAND_SDMESH :
406
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmesh_names, & fields->f_sd6);
407
      break;
408
    case EPIPHANY_OPERAND_SHIFT :
409
      errmsg = cgen_parse_unsigned_integer (cd, strp, EPIPHANY_OPERAND_SHIFT, (unsigned long *) (& fields->f_shift));
410
      break;
411
    case EPIPHANY_OPERAND_SIMM11 :
412
      errmsg = parse_simm_not_reg (cd, strp, EPIPHANY_OPERAND_SIMM11, (long *) (& fields->f_sdisp11));
413
      break;
414
    case EPIPHANY_OPERAND_SIMM24 :
415
      {
416
        bfd_vma value = 0;
417
        errmsg = parse_branch_addr (cd, strp, EPIPHANY_OPERAND_SIMM24, 0, NULL,  & value);
418
        fields->f_simm24 = value;
419
      }
420
      break;
421
    case EPIPHANY_OPERAND_SIMM3 :
422
      errmsg = parse_simm_not_reg (cd, strp, EPIPHANY_OPERAND_SIMM3, (long *) (& fields->f_sdisp3));
423
      break;
424
    case EPIPHANY_OPERAND_SIMM8 :
425
      {
426
        bfd_vma value = 0;
427
        errmsg = parse_branch_addr (cd, strp, EPIPHANY_OPERAND_SIMM8, 0, NULL,  & value);
428
        fields->f_simm8 = value;
429
      }
430
      break;
431
    case EPIPHANY_OPERAND_SN :
432
      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sn);
433
      break;
434
    case EPIPHANY_OPERAND_SN6 :
435
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sn6);
436
      break;
437
    case EPIPHANY_OPERAND_SNDMA :
438
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crdma_names, & fields->f_sn6);
439
      break;
440
    case EPIPHANY_OPERAND_SNMEM :
441
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmem_names, & fields->f_sn6);
442
      break;
443
    case EPIPHANY_OPERAND_SNMESH :
444
      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmesh_names, & fields->f_sn6);
445
      break;
446
    case EPIPHANY_OPERAND_SWI_NUM :
447
      errmsg = parse_uimm_not_reg (cd, strp, EPIPHANY_OPERAND_SWI_NUM, (unsigned long *) (& fields->f_trap_num));
448
      break;
449
    case EPIPHANY_OPERAND_TRAPNUM6 :
450
      errmsg = cgen_parse_unsigned_integer (cd, strp, EPIPHANY_OPERAND_TRAPNUM6, (unsigned long *) (& fields->f_trap_num));
451
      break;
452
 
453
    default :
454
      /* xgettext:c-format */
455
      fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
456
      abort ();
457
  }
458
 
459
  return errmsg;
460
}
461
 
462
cgen_parse_fn * const epiphany_cgen_parse_handlers[] =
463
{
464
  parse_insn_normal,
465
};
466
 
467
void
468
epiphany_cgen_init_asm (CGEN_CPU_DESC cd)
469
{
470
  epiphany_cgen_init_opcode_table (cd);
471
  epiphany_cgen_init_ibld_table (cd);
472
  cd->parse_handlers = & epiphany_cgen_parse_handlers[0];
473
  cd->parse_operand = epiphany_cgen_parse_operand;
474
#ifdef CGEN_ASM_INIT_HOOK
475
CGEN_ASM_INIT_HOOK
476
#endif
477
}
478
 
479
 
480
 
481
/* Regex construction routine.
482
 
483
   This translates an opcode syntax string into a regex string,
484
   by replacing any non-character syntax element (such as an
485
   opcode) with the pattern '.*'
486
 
487
   It then compiles the regex and stores it in the opcode, for
488
   later use by epiphany_cgen_assemble_insn
489
 
490
   Returns NULL for success, an error message for failure.  */
491
 
492
char *
493
epiphany_cgen_build_insn_regex (CGEN_INSN *insn)
494
{
495
  CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
496
  const char *mnem = CGEN_INSN_MNEMONIC (insn);
497
  char rxbuf[CGEN_MAX_RX_ELEMENTS];
498
  char *rx = rxbuf;
499
  const CGEN_SYNTAX_CHAR_TYPE *syn;
500
  int reg_err;
501
 
502
  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
503
 
504
  /* Mnemonics come first in the syntax string.  */
505
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
506
    return _("missing mnemonic in syntax string");
507
  ++syn;
508
 
509
  /* Generate a case sensitive regular expression that emulates case
510
     insensitive matching in the "C" locale.  We cannot generate a case
511
     insensitive regular expression because in Turkish locales, 'i' and 'I'
512
     are not equal modulo case conversion.  */
513
 
514
  /* Copy the literal mnemonic out of the insn.  */
515
  for (; *mnem; mnem++)
516
    {
517
      char c = *mnem;
518
 
519
      if (ISALPHA (c))
520
        {
521
          *rx++ = '[';
522
          *rx++ = TOLOWER (c);
523
          *rx++ = TOUPPER (c);
524
          *rx++ = ']';
525
        }
526
      else
527
        *rx++ = c;
528
    }
529
 
530
  /* Copy any remaining literals from the syntax string into the rx.  */
531
  for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
532
    {
533
      if (CGEN_SYNTAX_CHAR_P (* syn))
534
        {
535
          char c = CGEN_SYNTAX_CHAR (* syn);
536
 
537
          switch (c)
538
            {
539
              /* Escape any regex metacharacters in the syntax.  */
540
            case '.': case '[': case '\\':
541
            case '*': case '^': case '$':
542
 
543
#ifdef CGEN_ESCAPE_EXTENDED_REGEX
544
            case '?': case '{': case '}':
545
            case '(': case ')': case '*':
546
            case '|': case '+': case ']':
547
#endif
548
              *rx++ = '\\';
549
              *rx++ = c;
550
              break;
551
 
552
            default:
553
              if (ISALPHA (c))
554
                {
555
                  *rx++ = '[';
556
                  *rx++ = TOLOWER (c);
557
                  *rx++ = TOUPPER (c);
558
                  *rx++ = ']';
559
                }
560
              else
561
                *rx++ = c;
562
              break;
563
            }
564
        }
565
      else
566
        {
567
          /* Replace non-syntax fields with globs.  */
568
          *rx++ = '.';
569
          *rx++ = '*';
570
        }
571
    }
572
 
573
  /* Trailing whitespace ok.  */
574
  * rx++ = '[';
575
  * rx++ = ' ';
576
  * rx++ = '\t';
577
  * rx++ = ']';
578
  * rx++ = '*';
579
 
580
  /* But anchor it after that.  */
581
  * rx++ = '$';
582
  * rx = '\0';
583
 
584
  CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
585
  reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
586
 
587
  if (reg_err == 0)
588
    return NULL;
589
  else
590
    {
591
      static char msg[80];
592
 
593
      regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
594
      regfree ((regex_t *) CGEN_INSN_RX (insn));
595
      free (CGEN_INSN_RX (insn));
596
      (CGEN_INSN_RX (insn)) = NULL;
597
      return msg;
598
    }
599
}
600
 
601
 
602
/* Default insn parser.
603
 
604
   The syntax string is scanned and operands are parsed and stored in FIELDS.
605
   Relocs are queued as we go via other callbacks.
606
 
607
   ??? Note that this is currently an all-or-nothing parser.  If we fail to
608
   parse the instruction, we return 0 and the caller will start over from
609
   the beginning.  Backtracking will be necessary in parsing subexpressions,
610
   but that can be handled there.  Not handling backtracking here may get
611
   expensive in the case of the m68k.  Deal with later.
612
 
613
   Returns NULL for success, an error message for failure.  */
614
 
615
static const char *
616
parse_insn_normal (CGEN_CPU_DESC cd,
617
                   const CGEN_INSN *insn,
618
                   const char **strp,
619
                   CGEN_FIELDS *fields)
620
{
621
  /* ??? Runtime added insns not handled yet.  */
622
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
623
  const char *str = *strp;
624
  const char *errmsg;
625
  const char *p;
626
  const CGEN_SYNTAX_CHAR_TYPE * syn;
627
#ifdef CGEN_MNEMONIC_OPERANDS
628
  /* FIXME: wip */
629
  int past_opcode_p;
630
#endif
631
 
632
  /* For now we assume the mnemonic is first (there are no leading operands).
633
     We can parse it without needing to set up operand parsing.
634
     GAS's input scrubber will ensure mnemonics are lowercase, but we may
635
     not be called from GAS.  */
636
  p = CGEN_INSN_MNEMONIC (insn);
637
  while (*p && TOLOWER (*p) == TOLOWER (*str))
638
    ++p, ++str;
639
 
640
  if (* p)
641
    return _("unrecognized instruction");
642
 
643
#ifndef CGEN_MNEMONIC_OPERANDS
644
  if (* str && ! ISSPACE (* str))
645
    return _("unrecognized instruction");
646
#endif
647
 
648
  CGEN_INIT_PARSE (cd);
649
  cgen_init_parse_operand (cd);
650
#ifdef CGEN_MNEMONIC_OPERANDS
651
  past_opcode_p = 0;
652
#endif
653
 
654
  /* We don't check for (*str != '\0') here because we want to parse
655
     any trailing fake arguments in the syntax string.  */
656
  syn = CGEN_SYNTAX_STRING (syntax);
657
 
658
  /* Mnemonics come first for now, ensure valid string.  */
659
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
660
    abort ();
661
 
662
  ++syn;
663
 
664
  while (* syn != 0)
665
    {
666
      /* Non operand chars must match exactly.  */
667
      if (CGEN_SYNTAX_CHAR_P (* syn))
668
        {
669
          /* FIXME: While we allow for non-GAS callers above, we assume the
670
             first char after the mnemonic part is a space.  */
671
          /* FIXME: We also take inappropriate advantage of the fact that
672
             GAS's input scrubber will remove extraneous blanks.  */
673
          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
674
            {
675
#ifdef CGEN_MNEMONIC_OPERANDS
676
              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
677
                past_opcode_p = 1;
678
#endif
679
              ++ syn;
680
              ++ str;
681
            }
682
          else if (*str)
683
            {
684
              /* Syntax char didn't match.  Can't be this insn.  */
685
              static char msg [80];
686
 
687
              /* xgettext:c-format */
688
              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
689
                       CGEN_SYNTAX_CHAR(*syn), *str);
690
              return msg;
691
            }
692
          else
693
            {
694
              /* Ran out of input.  */
695
              static char msg [80];
696
 
697
              /* xgettext:c-format */
698
              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
699
                       CGEN_SYNTAX_CHAR(*syn));
700
              return msg;
701
            }
702
          continue;
703
        }
704
 
705
#ifdef CGEN_MNEMONIC_OPERANDS
706
      (void) past_opcode_p;
707
#endif
708
      /* We have an operand of some sort.  */
709
      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
710
      if (errmsg)
711
        return errmsg;
712
 
713
      /* Done with this operand, continue with next one.  */
714
      ++ syn;
715
    }
716
 
717
  /* If we're at the end of the syntax string, we're done.  */
718
  if (* syn == 0)
719
    {
720
      /* FIXME: For the moment we assume a valid `str' can only contain
721
         blanks now.  IE: We needn't try again with a longer version of
722
         the insn and it is assumed that longer versions of insns appear
723
         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
724
      while (ISSPACE (* str))
725
        ++ str;
726
 
727
      if (* str != '\0')
728
        return _("junk at end of line"); /* FIXME: would like to include `str' */
729
 
730
      return NULL;
731
    }
732
 
733
  /* We couldn't parse it.  */
734
  return _("unrecognized instruction");
735
}
736
 
737
/* Main entry point.
738
   This routine is called for each instruction to be assembled.
739
   STR points to the insn to be assembled.
740
   We assume all necessary tables have been initialized.
741
   The assembled instruction, less any fixups, is stored in BUF.
742
   Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
743
   still needs to be converted to target byte order, otherwise BUF is an array
744
   of bytes in target byte order.
745
   The result is a pointer to the insn's entry in the opcode table,
746
   or NULL if an error occured (an error message will have already been
747
   printed).
748
 
749
   Note that when processing (non-alias) macro-insns,
750
   this function recurses.
751
 
752
   ??? It's possible to make this cpu-independent.
753
   One would have to deal with a few minor things.
754
   At this point in time doing so would be more of a curiosity than useful
755
   [for example this file isn't _that_ big], but keeping the possibility in
756
   mind helps keep the design clean.  */
757
 
758
const CGEN_INSN *
759
epiphany_cgen_assemble_insn (CGEN_CPU_DESC cd,
760
                           const char *str,
761
                           CGEN_FIELDS *fields,
762
                           CGEN_INSN_BYTES_PTR buf,
763
                           char **errmsg)
764
{
765
  const char *start;
766
  CGEN_INSN_LIST *ilist;
767
  const char *parse_errmsg = NULL;
768
  const char *insert_errmsg = NULL;
769
  int recognized_mnemonic = 0;
770
 
771
  /* Skip leading white space.  */
772
  while (ISSPACE (* str))
773
    ++ str;
774
 
775
  /* The instructions are stored in hashed lists.
776
     Get the first in the list.  */
777
  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
778
 
779
  /* Keep looking until we find a match.  */
780
  start = str;
781
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
782
    {
783
      const CGEN_INSN *insn = ilist->insn;
784
      recognized_mnemonic = 1;
785
 
786
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
787
      /* Not usually needed as unsupported opcodes
788
         shouldn't be in the hash lists.  */
789
      /* Is this insn supported by the selected cpu?  */
790
      if (! epiphany_cgen_insn_supported (cd, insn))
791
        continue;
792
#endif
793
      /* If the RELAXED attribute is set, this is an insn that shouldn't be
794
         chosen immediately.  Instead, it is used during assembler/linker
795
         relaxation if possible.  */
796
      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
797
        continue;
798
 
799
      str = start;
800
 
801
      /* Skip this insn if str doesn't look right lexically.  */
802
      if (CGEN_INSN_RX (insn) != NULL &&
803
          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
804
        continue;
805
 
806
      /* Allow parse/insert handlers to obtain length of insn.  */
807
      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
808
 
809
      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
810
      if (parse_errmsg != NULL)
811
        continue;
812
 
813
      /* ??? 0 is passed for `pc'.  */
814
      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
815
                                                 (bfd_vma) 0);
816
      if (insert_errmsg != NULL)
817
        continue;
818
 
819
      /* It is up to the caller to actually output the insn and any
820
         queued relocs.  */
821
      return insn;
822
    }
823
 
824
  {
825
    static char errbuf[150];
826
    const char *tmp_errmsg;
827
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
828
#define be_verbose 1
829
#else
830
#define be_verbose 0
831
#endif
832
 
833
    if (be_verbose)
834
      {
835
        /* If requesting verbose error messages, use insert_errmsg.
836
           Failing that, use parse_errmsg.  */
837
        tmp_errmsg = (insert_errmsg ? insert_errmsg :
838
                      parse_errmsg ? parse_errmsg :
839
                      recognized_mnemonic ?
840
                      _("unrecognized form of instruction") :
841
                      _("unrecognized instruction"));
842
 
843
        if (strlen (start) > 50)
844
          /* xgettext:c-format */
845
          sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
846
        else
847
          /* xgettext:c-format */
848
          sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
849
      }
850
    else
851
      {
852
        if (strlen (start) > 50)
853
          /* xgettext:c-format */
854
          sprintf (errbuf, _("bad instruction `%.50s...'"), start);
855
        else
856
          /* xgettext:c-format */
857
          sprintf (errbuf, _("bad instruction `%.50s'"), start);
858
      }
859
 
860
    *errmsg = errbuf;
861
    return NULL;
862
  }
863
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.