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

Subversion Repositories open8_urisc

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

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

powered by: WebSVN 2.1.0

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