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

Subversion Repositories open8_urisc

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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