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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [opcodes/] [ip2k-asm.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* 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 Free Software Foundation, Inc.
8
 
9
This file is part of the GNU Binutils and GDB, the GNU debugger.
10
 
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 2, or (at your option)
14
any later version.
15
 
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
GNU General Public License for more details.
20
 
21
You should have received a copy of the GNU General Public License
22
along with this program; if not, write to the Free Software Foundation, Inc.,
23
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
24
 
25
/* ??? Eventually more and more of this stuff can go to cpu-independent files.
26
   Keep that in mind.  */
27
 
28
#include "sysdep.h"
29
#include <stdio.h>
30
#include "ansidecl.h"
31
#include "bfd.h"
32
#include "symcat.h"
33
#include "ip2k-desc.h"
34
#include "ip2k-opc.h"
35
#include "opintl.h"
36
#include "xregex.h"
37
#include "libiberty.h"
38
#include "safe-ctype.h"
39
 
40
#undef  min
41
#define min(a,b) ((a) < (b) ? (a) : (b))
42
#undef  max
43
#define max(a,b) ((a) > (b) ? (a) : (b))
44
 
45
static const char * parse_insn_normal
46
     PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
47
 
48
/* -- assembler routines inserted here.  */
49
 
50
/* -- asm.c */
51
 
52
static const char *
53
parse_fr (cd, strp, opindex, valuep)
54
     CGEN_CPU_DESC cd;
55
     const char **strp;
56
     int opindex;
57
     long *valuep;
58
{
59
  const char *errmsg;
60
  char *old_strp;
61
  char *afteroffset;
62
  enum cgen_parse_operand_result result_type;
63
  bfd_vma value;
64
  extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
65
  long tempvalue;
66
 
67
  old_strp = *strp;
68
  afteroffset = NULL;
69
 
70
 
71
  /* Check here to see if you're about to try parsing a w as the first arg */
72
  /* and return an error if you are.                                       */
73
  if ( (strncmp(*strp,"w",1)==0) || (strncmp(*strp,"W",1)==0) )
74
  {
75
     (*strp)++;
76
 
77
     if ( (strncmp(*strp,",",1)==0) || isspace(**strp) )
78
     {
79
        /* We've been passed a w.  Return with an error message so that  */
80
        /* cgen will try the next parsing option.                        */
81
        errmsg = _("W keyword invalid in FR operand slot.");
82
        return errmsg;
83
     }
84
     *strp = old_strp;
85
  }
86
 
87
 
88
  /* Attempt parse as register keyword. */
89
  /* old_strp = *strp; */
90
 
91
  errmsg = cgen_parse_keyword (cd, strp, & ip2k_cgen_opval_register_names, valuep);
92
  if ( *strp != NULL )
93
  if (errmsg == NULL)
94
    return errmsg;
95
 
96
  /* Attempt to parse for "(IP)" */
97
  afteroffset = strstr(*strp,"(IP)");
98
 
99
  if ( afteroffset == NULL)
100
  {
101
     /* Make sure it's not in lower case */
102
     afteroffset = strstr(*strp,"(ip)");
103
  }
104
 
105
  if ( afteroffset != NULL )
106
    {
107
      if ( afteroffset != *strp )
108
        {
109
          /* Invalid offset present.*/
110
          errmsg = _("offset(IP) is not a valid form");
111
          return errmsg;
112
        }
113
      else
114
        {
115
          *strp += 4;
116
          *valuep = 0;
117
          errmsg = NULL;
118
          return errmsg;
119
        }
120
    }
121
 
122
  /* Attempt to parse for DP. ex: mov w, offset(DP)  */
123
  /*                              mov offset(DP),w   */
124
 
125
  /* Try parsing it as an address and see what comes back */
126
 
127
  afteroffset = strstr(*strp,"(DP)");
128
 
129
  if ( afteroffset == NULL)
130
  {
131
     /* Maybe it's in lower case */
132
     afteroffset = strstr(*strp,"(dp)");
133
  }
134
 
135
  if ( afteroffset != NULL )
136
  {
137
     if ( afteroffset == *strp )
138
     {
139
        /* No offset present. Use 0 by default. */
140
        tempvalue = 0;
141
        errmsg = NULL;
142
     }
143
     else
144
     {
145
       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR_OFFSET,
146
                                    & result_type, & tempvalue);
147
     }
148
 
149
     if (errmsg == NULL)
150
     {
151
        if ( (tempvalue >= 0) && (tempvalue <= 127) )
152
        {
153
           /* Value is ok.  Fix up the first 2 bits and return */
154
           *valuep = 0x0100 | tempvalue;
155
           *strp += 4; /* skip over the (DP) in *strp */
156
           return errmsg;
157
        } else
158
        {
159
           /* Found something there in front of (DP) but it's out of range. */
160
           errmsg = _("(DP) offset out of range.");
161
           return errmsg;
162
        }
163
 
164
     }
165
  }
166
 
167
 
168
  /* Attempt to parse for SP. ex: mov w, offset(SP)  */
169
  /*                              mov offset(SP), w  */
170
 
171
 
172
  afteroffset = strstr(*strp,"(SP)");
173
 
174
  if (afteroffset == NULL)
175
  {
176
     /* Maybe it's in lower case. */
177
     afteroffset = strstr(*strp, "(sp)");
178
  }
179
 
180
  if ( afteroffset != NULL )
181
  {
182
     if ( afteroffset ==  *strp )
183
     {
184
        /* No offset present. Use 0 by default. */
185
        tempvalue = 0;
186
        errmsg = NULL;
187
     }
188
     else
189
     {
190
       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR_OFFSET,
191
                                    & result_type, & tempvalue);
192
     }
193
     if (errmsg == NULL)
194
     {
195
        if ( (tempvalue >= 0) && (tempvalue <= 127) )
196
        {
197
           /* Value is ok.  Fix up the first 2 bits and return */
198
           *valuep = 0x0180 | tempvalue;
199
           *strp += 4; /* skip over the (SP) in *strp */
200
           return errmsg;
201
        } else
202
        {
203
           /* Found something there in front of (SP) but it's out of range. */
204
           errmsg = _("(SP) offset out of range.");
205
           return errmsg;
206
        }
207
 
208
     }
209
  }
210
 
211
 
212
  /* Attempt to parse as an address. */
213
  *strp = old_strp;
214
  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR9,
215
                               & result_type, & value);
216
  if (errmsg == NULL)
217
    {
218
      *valuep = value;
219
 
220
      /* if a parenthesis is found, warn about invalid form */
221
 
222
      if (**strp == '(')
223
        {
224
          errmsg = _("illegal use of parentheses");
225
        }
226
      /* if a numeric value is specified, ensure that it is between 1 and 255 */
227
      else if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
228
        {
229
          if (value < 0x1 || value > 0xff)
230
            errmsg = _("operand out of range (not between 1 and 255)");
231
        }
232
    }
233
  return errmsg;
234
}
235
 
236
static const char *
237
parse_addr16 (cd, strp, opindex, valuep)
238
     CGEN_CPU_DESC cd;
239
     const char **strp;
240
     int opindex;
241
     long *valuep;
242
{
243
  const char *errmsg;
244
  enum cgen_parse_operand_result result_type;
245
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
246
  long value;
247
 
248
  if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16H )
249
      code = BFD_RELOC_IP2K_HI8DATA;
250
  else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16L )
251
      code = BFD_RELOC_IP2K_LO8DATA;
252
  else
253
    {
254
      /* Something is very wrong. opindex has to be one of the above. */
255
      errmsg = _("parse_addr16: invalid opindex.");
256
      return errmsg;
257
    }
258
 
259
  errmsg = cgen_parse_address (cd, strp, opindex, code,
260
                                  & result_type, & value);
261
  if (errmsg == NULL)
262
    {
263
       /* We either have a relocation or a number now. */
264
      if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
265
      {
266
         /* We got a number back. */
267
         if ( code == BFD_RELOC_IP2K_HI8DATA )
268
            value >>= 8;
269
         else    /* code = BFD_RELOC_IP2K_LOW8DATA */
270
            value &= 0x00FF;
271
      }
272
         *valuep = value;
273
   }
274
 
275
  return errmsg;
276
}
277
 
278
 
279
 static const char *
280
 parse_addr16_p (cd, strp, opindex, valuep)
281
      CGEN_CPU_DESC cd;
282
      const char **strp;
283
      int opindex;
284
      long *valuep;
285
 {
286
   const char *errmsg;
287
   enum cgen_parse_operand_result result_type;
288
   bfd_reloc_code_real_type code = BFD_RELOC_IP2K_PAGE3;
289
   long value;
290
 
291
   errmsg = cgen_parse_address (cd, strp, opindex, code,
292
                                 & result_type, & value);
293
   if (errmsg == NULL)
294
   {
295
       if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
296
            *valuep = (value >> 13) & 0x7;
297
       else if ( result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED )
298
            *valuep = value;
299
   }
300
   return errmsg;
301
 }
302
 
303
 
304
 static const char *
305
 parse_addr16_cjp (cd, strp, opindex, valuep)
306
      CGEN_CPU_DESC cd;
307
      const char **strp;
308
      int opindex;
309
      long *valuep;
310
 {
311
   const char *errmsg;
312
   enum cgen_parse_operand_result result_type;
313
   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
314
   long value;
315
 
316
   if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16CJP )
317
      code = BFD_RELOC_IP2K_ADDR16CJP;
318
   else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16P )
319
      code = BFD_RELOC_IP2K_PAGE3;
320
 
321
   errmsg = cgen_parse_address (cd, strp, opindex, code,
322
                                 & result_type, & value);
323
   if (errmsg == NULL)
324
   {
325
       if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
326
       {
327
         if ( (value & 0x1) == 0)  /* If the address is even .... */
328
         {
329
             if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16CJP )
330
                *valuep = (value >> 1) & 0x1FFF;  /* Should mask be 1FFF? */
331
             else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16P )
332
                *valuep = (value >> 14) & 0x7;
333
          }
334
          else
335
            errmsg = _("Byte address required. - must be even.");
336
       }else if ( result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED )
337
       {
338
            /* This will happen for things like (s2-s1) where s2 and s1 */
339
            /* are labels.                                              */
340
            *valuep = value;
341
        }
342
      else
343
        errmsg = _("cgen_parse_address returned a symbol. Literal required.");
344
   }
345
   return errmsg;
346
 }
347
 
348
 
349
static const char *
350
parse_lit8 (cd, strp, opindex, valuep)
351
     CGEN_CPU_DESC cd;
352
     const char **strp;
353
     int opindex;
354
     long *valuep;
355
{
356
  const char *errmsg;
357
  enum cgen_parse_operand_result result_type;
358
  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
359
  long value;
360
 
361
  /* Parse %OP relocating operators. */
362
  if (strncmp (*strp, "%bank", 5) == 0)
363
    {
364
      *strp += 5;
365
      code = BFD_RELOC_IP2K_BANK;
366
    }
367
  else if (strncmp (*strp, "%lo8data", 8) == 0)
368
    {
369
      *strp += 8;
370
      code = BFD_RELOC_IP2K_LO8DATA;
371
    }
372
  else if (strncmp (*strp, "%hi8data", 8) == 0)
373
    {
374
      *strp += 8;
375
      code = BFD_RELOC_IP2K_HI8DATA;
376
    }
377
  else if (strncmp (*strp, "%ex8data", 8) == 0)
378
    {
379
      *strp += 8;
380
      code = BFD_RELOC_IP2K_EX8DATA;
381
    }
382
  else if (strncmp (*strp, "%lo8insn", 8) == 0)
383
    {
384
      *strp += 8;
385
      code = BFD_RELOC_IP2K_LO8INSN;
386
    }
387
  else if (strncmp (*strp, "%hi8insn", 8) == 0)
388
    {
389
      *strp += 8;
390
      code = BFD_RELOC_IP2K_HI8INSN;
391
    }
392
 
393
 
394
  /* Parse %op operand.  */
395
  if (code != BFD_RELOC_NONE)
396
    {
397
      errmsg = cgen_parse_address (cd, strp, opindex, code,
398
                                   & result_type, & value);
399
      if ((errmsg == NULL) &&
400
          (result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED))
401
        errmsg = _("%operator operand is not a symbol");
402
 
403
      *valuep = value;
404
    }
405
  /* Parse as a number.  */
406
  else
407
    {
408
      errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
409
 
410
      /* Truncate to eight bits to accept both signed and unsigned input. */
411
      if (errmsg == NULL)
412
        *valuep &= 0xFF;
413
    }
414
 
415
  return errmsg;
416
}
417
 
418
static const char *
419
parse_bit3 (cd, strp, opindex, valuep)
420
     CGEN_CPU_DESC cd;
421
     const char **strp;
422
     int opindex;
423
     long *valuep;
424
{
425
  const char *errmsg;
426
  char mode = 0;
427
  long count = 0;
428
  unsigned long value;
429
 
430
  if (strncmp (*strp, "%bit", 4) == 0)
431
    {
432
      *strp += 4;
433
      mode = 1;
434
    }
435
  else if (strncmp (*strp, "%msbbit", 7) == 0)
436
    {
437
      *strp += 7;
438
      mode = 1;
439
    }
440
  else if (strncmp (*strp, "%lsbbit", 7) == 0)
441
    {
442
      *strp += 7;
443
      mode = 2;
444
    }
445
 
446
  errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
447
  if (errmsg) {
448
    return errmsg;
449
  }
450
 
451
  if (mode) {
452
    value = (unsigned long) *valuep;
453
    if (value == 0) {
454
      errmsg = _("Attempt to find bit index of 0");
455
      return errmsg;
456
    }
457
 
458
    if (mode == 1) {
459
      count = 31;
460
      while ((value & 0x80000000) == 0) {
461
        count--;
462
        value <<= 1;
463
      }
464
    } else if (mode == 2) {
465
      count = 0;
466
      while ((value & 0x00000001) == 0) {
467
        count++;
468
        value >>= 1;
469
      }
470
    }
471
 
472
    *valuep = count;
473
  }
474
 
475
  return errmsg;
476
}
477
 
478
 
479
/* -- dis.c */
480
 
481
const char * ip2k_cgen_parse_operand
482
  PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
483
 
484
/* Main entry point for operand parsing.
485
 
486
   This function is basically just a big switch statement.  Earlier versions
487
   used tables to look up the function to use, but
488
   - if the table contains both assembler and disassembler functions then
489
     the disassembler contains much of the assembler and vice-versa,
490
   - there's a lot of inlining possibilities as things grow,
491
   - using a switch statement avoids the function call overhead.
492
 
493
   This function could be moved into `parse_insn_normal', but keeping it
494
   separate makes clear the interface between `parse_insn_normal' and each of
495
   the handlers.  */
496
 
497
const char *
498
ip2k_cgen_parse_operand (cd, opindex, strp, fields)
499
     CGEN_CPU_DESC cd;
500
     int opindex;
501
     const char ** strp;
502
     CGEN_FIELDS * fields;
503
{
504
  const char * errmsg = NULL;
505
  /* Used by scalar operands that still need to be parsed.  */
506
  long junk ATTRIBUTE_UNUSED;
507
 
508
  switch (opindex)
509
    {
510
    case IP2K_OPERAND_ADDR16CJP :
511
      errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16CJP, &fields->f_addr16cjp);
512
      break;
513
    case IP2K_OPERAND_ADDR16H :
514
      errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16H, &fields->f_imm8);
515
      break;
516
    case IP2K_OPERAND_ADDR16L :
517
      errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16L, &fields->f_imm8);
518
      break;
519
    case IP2K_OPERAND_ADDR16P :
520
      errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16P, &fields->f_page3);
521
      break;
522
    case IP2K_OPERAND_BITNO :
523
      errmsg = parse_bit3 (cd, strp, IP2K_OPERAND_BITNO, &fields->f_bitno);
524
      break;
525
    case IP2K_OPERAND_CBIT :
526
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_CBIT, &junk);
527
      break;
528
    case IP2K_OPERAND_DCBIT :
529
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_DCBIT, &junk);
530
      break;
531
    case IP2K_OPERAND_FR :
532
      errmsg = parse_fr (cd, strp, IP2K_OPERAND_FR, &fields->f_reg);
533
      break;
534
    case IP2K_OPERAND_LIT8 :
535
      errmsg = parse_lit8 (cd, strp, IP2K_OPERAND_LIT8, &fields->f_imm8);
536
      break;
537
    case IP2K_OPERAND_PABITS :
538
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_PABITS, &junk);
539
      break;
540
    case IP2K_OPERAND_RETI3 :
541
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_RETI3, &fields->f_reti3);
542
      break;
543
    case IP2K_OPERAND_ZBIT :
544
      errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_ZBIT, &junk);
545
      break;
546
 
547
    default :
548
      /* xgettext:c-format */
549
      fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
550
      abort ();
551
  }
552
 
553
  return errmsg;
554
}
555
 
556
cgen_parse_fn * const ip2k_cgen_parse_handlers[] =
557
{
558
  parse_insn_normal,
559
};
560
 
561
void
562
ip2k_cgen_init_asm (cd)
563
     CGEN_CPU_DESC cd;
564
{
565
  ip2k_cgen_init_opcode_table (cd);
566
  ip2k_cgen_init_ibld_table (cd);
567
  cd->parse_handlers = & ip2k_cgen_parse_handlers[0];
568
  cd->parse_operand = ip2k_cgen_parse_operand;
569
}
570
 
571
 
572
 
573
/* Regex construction routine.
574
 
575
   This translates an opcode syntax string into a regex string,
576
   by replacing any non-character syntax element (such as an
577
   opcode) with the pattern '.*'
578
 
579
   It then compiles the regex and stores it in the opcode, for
580
   later use by ip2k_cgen_assemble_insn
581
 
582
   Returns NULL for success, an error message for failure.  */
583
 
584
char *
585
ip2k_cgen_build_insn_regex (insn)
586
     CGEN_INSN *insn;
587
{
588
  CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
589
  const char *mnem = CGEN_INSN_MNEMONIC (insn);
590
  char rxbuf[CGEN_MAX_RX_ELEMENTS];
591
  char *rx = rxbuf;
592
  const CGEN_SYNTAX_CHAR_TYPE *syn;
593
  int reg_err;
594
 
595
  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
596
 
597
  /* Mnemonics come first in the syntax string.  */
598
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
599
    return _("missing mnemonic in syntax string");
600
  ++syn;
601
 
602
  /* Generate a case sensitive regular expression that emulates case
603
     insensitive matching in the "C" locale.  We cannot generate a case
604
     insensitive regular expression because in Turkish locales, 'i' and 'I'
605
     are not equal modulo case conversion.  */
606
 
607
  /* Copy the literal mnemonic out of the insn.  */
608
  for (; *mnem; mnem++)
609
    {
610
      char c = *mnem;
611
 
612
      if (ISALPHA (c))
613
        {
614
          *rx++ = '[';
615
          *rx++ = TOLOWER (c);
616
          *rx++ = TOUPPER (c);
617
          *rx++ = ']';
618
        }
619
      else
620
        *rx++ = c;
621
    }
622
 
623
  /* Copy any remaining literals from the syntax string into the rx.  */
624
  for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
625
    {
626
      if (CGEN_SYNTAX_CHAR_P (* syn))
627
        {
628
          char c = CGEN_SYNTAX_CHAR (* syn);
629
 
630
          switch (c)
631
            {
632
              /* Escape any regex metacharacters in the syntax.  */
633
            case '.': case '[': case '\\':
634
            case '*': case '^': case '$':
635
 
636
#ifdef CGEN_ESCAPE_EXTENDED_REGEX
637
            case '?': case '{': case '}':
638
            case '(': case ')': case '*':
639
            case '|': case '+': case ']':
640
#endif
641
              *rx++ = '\\';
642
              *rx++ = c;
643
              break;
644
 
645
            default:
646
              if (ISALPHA (c))
647
                {
648
                  *rx++ = '[';
649
                  *rx++ = TOLOWER (c);
650
                  *rx++ = TOUPPER (c);
651
                  *rx++ = ']';
652
                }
653
              else
654
                *rx++ = c;
655
              break;
656
            }
657
        }
658
      else
659
        {
660
          /* Replace non-syntax fields with globs.  */
661
          *rx++ = '.';
662
          *rx++ = '*';
663
        }
664
    }
665
 
666
  /* Trailing whitespace ok.  */
667
  * rx++ = '[';
668
  * rx++ = ' ';
669
  * rx++ = '\t';
670
  * rx++ = ']';
671
  * rx++ = '*';
672
 
673
  /* But anchor it after that.  */
674
  * rx++ = '$';
675
  * rx = '\0';
676
 
677
  CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
678
  reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
679
 
680
  if (reg_err == 0)
681
    return NULL;
682
  else
683
    {
684
      static char msg[80];
685
 
686
      regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
687
      regfree ((regex_t *) CGEN_INSN_RX (insn));
688
      free (CGEN_INSN_RX (insn));
689
      (CGEN_INSN_RX (insn)) = NULL;
690
      return msg;
691
    }
692
}
693
 
694
 
695
/* Default insn parser.
696
 
697
   The syntax string is scanned and operands are parsed and stored in FIELDS.
698
   Relocs are queued as we go via other callbacks.
699
 
700
   ??? Note that this is currently an all-or-nothing parser.  If we fail to
701
   parse the instruction, we return 0 and the caller will start over from
702
   the beginning.  Backtracking will be necessary in parsing subexpressions,
703
   but that can be handled there.  Not handling backtracking here may get
704
   expensive in the case of the m68k.  Deal with later.
705
 
706
   Returns NULL for success, an error message for failure.  */
707
 
708
static const char *
709
parse_insn_normal (cd, insn, strp, fields)
710
     CGEN_CPU_DESC cd;
711
     const CGEN_INSN *insn;
712
     const char **strp;
713
     CGEN_FIELDS *fields;
714
{
715
  /* ??? Runtime added insns not handled yet.  */
716
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
717
  const char *str = *strp;
718
  const char *errmsg;
719
  const char *p;
720
  const CGEN_SYNTAX_CHAR_TYPE * syn;
721
#ifdef CGEN_MNEMONIC_OPERANDS
722
  /* FIXME: wip */
723
  int past_opcode_p;
724
#endif
725
 
726
  /* For now we assume the mnemonic is first (there are no leading operands).
727
     We can parse it without needing to set up operand parsing.
728
     GAS's input scrubber will ensure mnemonics are lowercase, but we may
729
     not be called from GAS.  */
730
  p = CGEN_INSN_MNEMONIC (insn);
731
  while (*p && TOLOWER (*p) == TOLOWER (*str))
732
    ++p, ++str;
733
 
734
  if (* p)
735
    return _("unrecognized instruction");
736
 
737
#ifndef CGEN_MNEMONIC_OPERANDS
738
  if (* str && ! ISSPACE (* str))
739
    return _("unrecognized instruction");
740
#endif
741
 
742
  CGEN_INIT_PARSE (cd);
743
  cgen_init_parse_operand (cd);
744
#ifdef CGEN_MNEMONIC_OPERANDS
745
  past_opcode_p = 0;
746
#endif
747
 
748
  /* We don't check for (*str != '\0') here because we want to parse
749
     any trailing fake arguments in the syntax string.  */
750
  syn = CGEN_SYNTAX_STRING (syntax);
751
 
752
  /* Mnemonics come first for now, ensure valid string.  */
753
  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
754
    abort ();
755
 
756
  ++syn;
757
 
758
  while (* syn != 0)
759
    {
760
      /* Non operand chars must match exactly.  */
761
      if (CGEN_SYNTAX_CHAR_P (* syn))
762
        {
763
          /* FIXME: While we allow for non-GAS callers above, we assume the
764
             first char after the mnemonic part is a space.  */
765
          /* FIXME: We also take inappropriate advantage of the fact that
766
             GAS's input scrubber will remove extraneous blanks.  */
767
          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
768
            {
769
#ifdef CGEN_MNEMONIC_OPERANDS
770
              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
771
                past_opcode_p = 1;
772
#endif
773
              ++ syn;
774
              ++ str;
775
            }
776
          else if (*str)
777
            {
778
              /* Syntax char didn't match.  Can't be this insn.  */
779
              static char msg [80];
780
 
781
              /* xgettext:c-format */
782
              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
783
                       CGEN_SYNTAX_CHAR(*syn), *str);
784
              return msg;
785
            }
786
          else
787
            {
788
              /* Ran out of input.  */
789
              static char msg [80];
790
 
791
              /* xgettext:c-format */
792
              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
793
                       CGEN_SYNTAX_CHAR(*syn));
794
              return msg;
795
            }
796
          continue;
797
        }
798
 
799
      /* We have an operand of some sort.  */
800
      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
801
                                          &str, fields);
802
      if (errmsg)
803
        return errmsg;
804
 
805
      /* Done with this operand, continue with next one.  */
806
      ++ syn;
807
    }
808
 
809
  /* If we're at the end of the syntax string, we're done.  */
810
  if (* syn == 0)
811
    {
812
      /* FIXME: For the moment we assume a valid `str' can only contain
813
         blanks now.  IE: We needn't try again with a longer version of
814
         the insn and it is assumed that longer versions of insns appear
815
         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
816
      while (ISSPACE (* str))
817
        ++ str;
818
 
819
      if (* str != '\0')
820
        return _("junk at end of line"); /* FIXME: would like to include `str' */
821
 
822
      return NULL;
823
    }
824
 
825
  /* We couldn't parse it.  */
826
  return _("unrecognized instruction");
827
}
828
 
829
/* Main entry point.
830
   This routine is called for each instruction to be assembled.
831
   STR points to the insn to be assembled.
832
   We assume all necessary tables have been initialized.
833
   The assembled instruction, less any fixups, is stored in BUF.
834
   Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
835
   still needs to be converted to target byte order, otherwise BUF is an array
836
   of bytes in target byte order.
837
   The result is a pointer to the insn's entry in the opcode table,
838
   or NULL if an error occured (an error message will have already been
839
   printed).
840
 
841
   Note that when processing (non-alias) macro-insns,
842
   this function recurses.
843
 
844
   ??? It's possible to make this cpu-independent.
845
   One would have to deal with a few minor things.
846
   At this point in time doing so would be more of a curiosity than useful
847
   [for example this file isn't _that_ big], but keeping the possibility in
848
   mind helps keep the design clean.  */
849
 
850
const CGEN_INSN *
851
ip2k_cgen_assemble_insn (cd, str, fields, buf, errmsg)
852
     CGEN_CPU_DESC cd;
853
     const char *str;
854
     CGEN_FIELDS *fields;
855
     CGEN_INSN_BYTES_PTR buf;
856
     char **errmsg;
857
{
858
  const char *start;
859
  CGEN_INSN_LIST *ilist;
860
  const char *parse_errmsg = NULL;
861
  const char *insert_errmsg = NULL;
862
  int recognized_mnemonic = 0;
863
 
864
  /* Skip leading white space.  */
865
  while (ISSPACE (* str))
866
    ++ str;
867
 
868
  /* The instructions are stored in hashed lists.
869
     Get the first in the list.  */
870
  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
871
 
872
  /* Keep looking until we find a match.  */
873
  start = str;
874
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
875
    {
876
      const CGEN_INSN *insn = ilist->insn;
877
      recognized_mnemonic = 1;
878
 
879
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
880
      /* Not usually needed as unsupported opcodes
881
         shouldn't be in the hash lists.  */
882
      /* Is this insn supported by the selected cpu?  */
883
      if (! ip2k_cgen_insn_supported (cd, insn))
884
        continue;
885
#endif
886
      /* If the RELAX attribute is set, this is an insn that shouldn't be
887
         chosen immediately.  Instead, it is used during assembler/linker
888
         relaxation if possible.  */
889
      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
890
        continue;
891
 
892
      str = start;
893
 
894
      /* Skip this insn if str doesn't look right lexically.  */
895
      if (CGEN_INSN_RX (insn) != NULL &&
896
          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
897
        continue;
898
 
899
      /* Allow parse/insert handlers to obtain length of insn.  */
900
      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
901
 
902
      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
903
      if (parse_errmsg != NULL)
904
        continue;
905
 
906
      /* ??? 0 is passed for `pc'.  */
907
      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
908
                                                 (bfd_vma) 0);
909
      if (insert_errmsg != NULL)
910
        continue;
911
 
912
      /* It is up to the caller to actually output the insn and any
913
         queued relocs.  */
914
      return insn;
915
    }
916
 
917
  {
918
    static char errbuf[150];
919
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
920
    const char *tmp_errmsg;
921
 
922
    /* If requesting verbose error messages, use insert_errmsg.
923
       Failing that, use parse_errmsg.  */
924
    tmp_errmsg = (insert_errmsg ? insert_errmsg :
925
                  parse_errmsg ? parse_errmsg :
926
                  recognized_mnemonic ?
927
                  _("unrecognized form of instruction") :
928
                  _("unrecognized instruction"));
929
 
930
    if (strlen (start) > 50)
931
      /* xgettext:c-format */
932
      sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
933
    else
934
      /* xgettext:c-format */
935
      sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
936
#else
937
    if (strlen (start) > 50)
938
      /* xgettext:c-format */
939
      sprintf (errbuf, _("bad instruction `%.50s...'"), start);
940
    else
941
      /* xgettext:c-format */
942
      sprintf (errbuf, _("bad instruction `%.50s'"), start);
943
#endif
944
 
945
    *errmsg = errbuf;
946
    return NULL;
947
  }
948
}
949
 
950
#if 0 /* This calls back to GAS which we can't do without care.  */
951
 
952
/* Record each member of OPVALS in the assembler's symbol table.
953
   This lets GAS parse registers for us.
954
   ??? Interesting idea but not currently used.  */
955
 
956
/* Record each member of OPVALS in the assembler's symbol table.
957
   FIXME: Not currently used.  */
958
 
959
void
960
ip2k_cgen_asm_hash_keywords (cd, opvals)
961
     CGEN_CPU_DESC cd;
962
     CGEN_KEYWORD *opvals;
963
{
964
  CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
965
  const CGEN_KEYWORD_ENTRY * ke;
966
 
967
  while ((ke = cgen_keyword_search_next (& search)) != NULL)
968
    {
969
#if 0 /* Unnecessary, should be done in the search routine.  */
970
      if (! ip2k_cgen_opval_supported (ke))
971
        continue;
972
#endif
973
      cgen_asm_record_register (cd, ke->name, ke->value);
974
    }
975
}
976
 
977
#endif /* 0 */

powered by: WebSVN 2.1.0

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