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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [opcodes/] [openrisc-asm.c] - Blame information for rev 853

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

Line No. Rev Author Line
1 38 julius
/* 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
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
      /* We have an operand of some sort.  */
492
      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
493
                                          &str, fields);
494
      if (errmsg)
495
        return errmsg;
496
 
497
      /* Done with this operand, continue with next one.  */
498
      ++ syn;
499
    }
500
 
501
  /* If we're at the end of the syntax string, we're done.  */
502
  if (* syn == 0)
503
    {
504
      /* FIXME: For the moment we assume a valid `str' can only contain
505
         blanks now.  IE: We needn't try again with a longer version of
506
         the insn and it is assumed that longer versions of insns appear
507
         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
508
      while (ISSPACE (* str))
509
        ++ str;
510
 
511
      if (* str != '\0')
512
        return _("junk at end of line"); /* FIXME: would like to include `str' */
513
 
514
      return NULL;
515
    }
516
 
517
  /* We couldn't parse it.  */
518
  return _("unrecognized instruction");
519
}
520
 
521
/* Main entry point.
522
   This routine is called for each instruction to be assembled.
523
   STR points to the insn to be assembled.
524
   We assume all necessary tables have been initialized.
525
   The assembled instruction, less any fixups, is stored in BUF.
526
   Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
527
   still needs to be converted to target byte order, otherwise BUF is an array
528
   of bytes in target byte order.
529
   The result is a pointer to the insn's entry in the opcode table,
530
   or NULL if an error occured (an error message will have already been
531
   printed).
532
 
533
   Note that when processing (non-alias) macro-insns,
534
   this function recurses.
535
 
536
   ??? It's possible to make this cpu-independent.
537
   One would have to deal with a few minor things.
538
   At this point in time doing so would be more of a curiosity than useful
539
   [for example this file isn't _that_ big], but keeping the possibility in
540
   mind helps keep the design clean.  */
541
 
542
const CGEN_INSN *
543
openrisc_cgen_assemble_insn (CGEN_CPU_DESC cd,
544
                           const char *str,
545
                           CGEN_FIELDS *fields,
546
                           CGEN_INSN_BYTES_PTR buf,
547
                           char **errmsg)
548
{
549
  const char *start;
550
  CGEN_INSN_LIST *ilist;
551
  const char *parse_errmsg = NULL;
552
  const char *insert_errmsg = NULL;
553
  int recognized_mnemonic = 0;
554
 
555
  /* Skip leading white space.  */
556
  while (ISSPACE (* str))
557
    ++ str;
558
 
559
  /* The instructions are stored in hashed lists.
560
     Get the first in the list.  */
561
  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
562
 
563
  /* Keep looking until we find a match.  */
564
  start = str;
565
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
566
    {
567
      const CGEN_INSN *insn = ilist->insn;
568
      recognized_mnemonic = 1;
569
 
570
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
571
      /* Not usually needed as unsupported opcodes
572
         shouldn't be in the hash lists.  */
573
      /* Is this insn supported by the selected cpu?  */
574
      if (! openrisc_cgen_insn_supported (cd, insn))
575
        continue;
576
#endif
577
      /* If the RELAXED attribute is set, this is an insn that shouldn't be
578
         chosen immediately.  Instead, it is used during assembler/linker
579
         relaxation if possible.  */
580
      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
581
        continue;
582
 
583
      str = start;
584
 
585
      /* Skip this insn if str doesn't look right lexically.  */
586
      if (CGEN_INSN_RX (insn) != NULL &&
587
          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
588
        continue;
589
 
590
      /* Allow parse/insert handlers to obtain length of insn.  */
591
      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
592
 
593
      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
594
      if (parse_errmsg != NULL)
595
        continue;
596
 
597
      /* ??? 0 is passed for `pc'.  */
598
      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
599
                                                 (bfd_vma) 0);
600
      if (insert_errmsg != NULL)
601
        continue;
602
 
603
      /* It is up to the caller to actually output the insn and any
604
         queued relocs.  */
605
      return insn;
606
    }
607
 
608
  {
609
    static char errbuf[150];
610
#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
611
    const char *tmp_errmsg;
612
 
613
    /* If requesting verbose error messages, use insert_errmsg.
614
       Failing that, use parse_errmsg.  */
615
    tmp_errmsg = (insert_errmsg ? insert_errmsg :
616
                  parse_errmsg ? parse_errmsg :
617
                  recognized_mnemonic ?
618
                  _("unrecognized form of instruction") :
619
                  _("unrecognized instruction"));
620
 
621
    if (strlen (start) > 50)
622
      /* xgettext:c-format */
623
      sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
624
    else
625
      /* xgettext:c-format */
626
      sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
627
#else
628
    if (strlen (start) > 50)
629
      /* xgettext:c-format */
630
      sprintf (errbuf, _("bad instruction `%.50s...'"), start);
631
    else
632
      /* xgettext:c-format */
633
      sprintf (errbuf, _("bad instruction `%.50s'"), start);
634
#endif
635
 
636
    *errmsg = errbuf;
637
    return NULL;
638
  }
639
}

powered by: WebSVN 2.1.0

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