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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [opcodes/] [cgen-opc.c] - Blame information for rev 866

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

Line No. Rev Author Line
1 38 julius
/* CGEN generic opcode support.
2
 
3
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005, 2007
4
   Free Software Foundation, Inc.
5
 
6
   This file is part of libopcodes.
7
 
8
   This library is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3, or (at your option)
11
   any later version.
12
 
13
   It is distributed in the hope that it will be useful, but WITHOUT
14
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16
   License for more details.
17
 
18
   You should have received a copy of the GNU General Public License along
19
   with this program; if not, write to the Free Software Foundation, Inc.,
20
   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
21
 
22
#include "sysdep.h"
23
#include <stdio.h>
24
#include "ansidecl.h"
25
#include "libiberty.h"
26
#include "safe-ctype.h"
27
#include "bfd.h"
28
#include "symcat.h"
29
#include "opcode/cgen.h"
30
 
31
#ifdef HAVE_ALLOCA_H
32
#include <alloca.h>
33
#endif
34
 
35
static unsigned int hash_keyword_name
36
  (const CGEN_KEYWORD *, const char *, int);
37
static unsigned int hash_keyword_value
38
  (const CGEN_KEYWORD *, unsigned int);
39
static void build_keyword_hash_tables
40
  (CGEN_KEYWORD *);
41
 
42
/* Return number of hash table entries to use for N elements.  */
43
#define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31)
44
 
45
/* Look up *NAMEP in the keyword table KT.
46
   The result is the keyword entry or NULL if not found.  */
47
 
48
const CGEN_KEYWORD_ENTRY *
49
cgen_keyword_lookup_name (CGEN_KEYWORD *kt, const char *name)
50
{
51
  const CGEN_KEYWORD_ENTRY *ke;
52
  const char *p,*n;
53
 
54
  if (kt->name_hash_table == NULL)
55
    build_keyword_hash_tables (kt);
56
 
57
  ke = kt->name_hash_table[hash_keyword_name (kt, name, 0)];
58
 
59
  /* We do case insensitive comparisons.
60
     If that ever becomes a problem, add an attribute that denotes
61
     "do case sensitive comparisons".  */
62
 
63
  while (ke != NULL)
64
    {
65
      n = name;
66
      p = ke->name;
67
 
68
      while (*p
69
             && (*p == *n
70
                 || (ISALPHA (*p) && (TOLOWER (*p) == TOLOWER (*n)))))
71
        ++n, ++p;
72
 
73
      if (!*p && !*n)
74
        return ke;
75
 
76
      ke = ke->next_name;
77
    }
78
 
79
  if (kt->null_entry)
80
    return kt->null_entry;
81
  return NULL;
82
}
83
 
84
/* Look up VALUE in the keyword table KT.
85
   The result is the keyword entry or NULL if not found.  */
86
 
87
const CGEN_KEYWORD_ENTRY *
88
cgen_keyword_lookup_value (CGEN_KEYWORD *kt, int value)
89
{
90
  const CGEN_KEYWORD_ENTRY *ke;
91
 
92
  if (kt->name_hash_table == NULL)
93
    build_keyword_hash_tables (kt);
94
 
95
  ke = kt->value_hash_table[hash_keyword_value (kt, value)];
96
 
97
  while (ke != NULL)
98
    {
99
      if (value == ke->value)
100
        return ke;
101
      ke = ke->next_value;
102
    }
103
 
104
  return NULL;
105
}
106
 
107
/* Add an entry to a keyword table.  */
108
 
109
void
110
cgen_keyword_add (CGEN_KEYWORD *kt, CGEN_KEYWORD_ENTRY *ke)
111
{
112
  unsigned int hash;
113
  size_t i;
114
 
115
  if (kt->name_hash_table == NULL)
116
    build_keyword_hash_tables (kt);
117
 
118
  hash = hash_keyword_name (kt, ke->name, 0);
119
  ke->next_name = kt->name_hash_table[hash];
120
  kt->name_hash_table[hash] = ke;
121
 
122
  hash = hash_keyword_value (kt, ke->value);
123
  ke->next_value = kt->value_hash_table[hash];
124
  kt->value_hash_table[hash] = ke;
125
 
126
  if (ke->name[0] == 0)
127
    kt->null_entry = ke;
128
 
129
  for (i = 1; i < strlen (ke->name); i++)
130
    if (! ISALNUM (ke->name[i])
131
        && ! strchr (kt->nonalpha_chars, ke->name[i]))
132
      {
133
        size_t idx = strlen (kt->nonalpha_chars);
134
 
135
        /* If you hit this limit, please don't just
136
           increase the size of the field, instead
137
           look for a better algorithm.  */
138
        if (idx >= sizeof (kt->nonalpha_chars) - 1)
139
          abort ();
140
        kt->nonalpha_chars[idx] = ke->name[i];
141
        kt->nonalpha_chars[idx+1] = 0;
142
      }
143
}
144
 
145
/* FIXME: Need function to return count of keywords.  */
146
 
147
/* Initialize a keyword table search.
148
   SPEC is a specification of what to search for.
149
   A value of NULL means to find every keyword.
150
   Currently NULL is the only acceptable value [further specification
151
   deferred].
152
   The result is an opaque data item used to record the search status.
153
   It is passed to each call to cgen_keyword_search_next.  */
154
 
155
CGEN_KEYWORD_SEARCH
156
cgen_keyword_search_init (CGEN_KEYWORD *kt, const char *spec)
157
{
158
  CGEN_KEYWORD_SEARCH search;
159
 
160
  /* FIXME: Need to specify format of params.  */
161
  if (spec != NULL)
162
    abort ();
163
 
164
  if (kt->name_hash_table == NULL)
165
    build_keyword_hash_tables (kt);
166
 
167
  search.table = kt;
168
  search.spec = spec;
169
  search.current_hash = 0;
170
  search.current_entry = NULL;
171
  return search;
172
}
173
 
174
/* Return the next keyword specified by SEARCH.
175
   The result is the next entry or NULL if there are no more.  */
176
 
177
const CGEN_KEYWORD_ENTRY *
178
cgen_keyword_search_next (CGEN_KEYWORD_SEARCH *search)
179
{
180
  /* Has search finished?  */
181
  if (search->current_hash == search->table->hash_table_size)
182
    return NULL;
183
 
184
  /* Search in progress?  */
185
  if (search->current_entry != NULL
186
      /* Anything left on this hash chain?  */
187
      && search->current_entry->next_name != NULL)
188
    {
189
      search->current_entry = search->current_entry->next_name;
190
      return search->current_entry;
191
    }
192
 
193
  /* Move to next hash chain [unless we haven't started yet].  */
194
  if (search->current_entry != NULL)
195
    ++search->current_hash;
196
 
197
  while (search->current_hash < search->table->hash_table_size)
198
    {
199
      search->current_entry = search->table->name_hash_table[search->current_hash];
200
      if (search->current_entry != NULL)
201
        return search->current_entry;
202
      ++search->current_hash;
203
    }
204
 
205
  return NULL;
206
}
207
 
208
/* Return first entry in hash chain for NAME.
209
   If CASE_SENSITIVE_P is non-zero, return a case sensitive hash.  */
210
 
211
static unsigned int
212
hash_keyword_name (const CGEN_KEYWORD *kt,
213
                   const char *name,
214
                   int case_sensitive_p)
215
{
216
  unsigned int hash;
217
 
218
  if (case_sensitive_p)
219
    for (hash = 0; *name; ++name)
220
      hash = (hash * 97) + (unsigned char) *name;
221
  else
222
    for (hash = 0; *name; ++name)
223
      hash = (hash * 97) + (unsigned char) TOLOWER (*name);
224
  return hash % kt->hash_table_size;
225
}
226
 
227
/* Return first entry in hash chain for VALUE.  */
228
 
229
static unsigned int
230
hash_keyword_value (const CGEN_KEYWORD *kt, unsigned int value)
231
{
232
  return value % kt->hash_table_size;
233
}
234
 
235
/* Build a keyword table's hash tables.
236
   We probably needn't build the value hash table for the assembler when
237
   we're using the disassembler, but we keep things simple.  */
238
 
239
static void
240
build_keyword_hash_tables (CGEN_KEYWORD *kt)
241
{
242
  int i;
243
  /* Use the number of compiled in entries as an estimate for the
244
     typical sized table [not too many added at runtime].  */
245
  unsigned int size = KEYWORD_HASH_SIZE (kt->num_init_entries);
246
 
247
  kt->hash_table_size = size;
248
  kt->name_hash_table = (CGEN_KEYWORD_ENTRY **)
249
    xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
250
  memset (kt->name_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
251
  kt->value_hash_table = (CGEN_KEYWORD_ENTRY **)
252
    xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
253
  memset (kt->value_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
254
 
255
  /* The table is scanned backwards as we want keywords appearing earlier to
256
     be prefered over later ones.  */
257
  for (i = kt->num_init_entries - 1; i >= 0; --i)
258
    cgen_keyword_add (kt, &kt->init_entries[i]);
259
}
260
 
261
/* Hardware support.  */
262
 
263
/* Lookup a hardware element by its name.
264
   Returns NULL if NAME is not supported by the currently selected
265
   mach/isa.  */
266
 
267
const CGEN_HW_ENTRY *
268
cgen_hw_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
269
{
270
  unsigned int i;
271
  const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
272
 
273
  for (i = 0; i < cd->hw_table.num_entries; ++i)
274
    if (hw[i] && strcmp (name, hw[i]->name) == 0)
275
      return hw[i];
276
 
277
  return NULL;
278
}
279
 
280
/* Lookup a hardware element by its number.
281
   Hardware elements are enumerated, however it may be possible to add some
282
   at runtime, thus HWNUM is not an enum type but rather an int.
283
   Returns NULL if HWNUM is not supported by the currently selected mach.  */
284
 
285
const CGEN_HW_ENTRY *
286
cgen_hw_lookup_by_num (CGEN_CPU_DESC cd, unsigned int hwnum)
287
{
288
  unsigned int i;
289
  const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
290
 
291
  /* ??? This can be speeded up.  */
292
  for (i = 0; i < cd->hw_table.num_entries; ++i)
293
    if (hw[i] && hwnum == hw[i]->type)
294
      return hw[i];
295
 
296
  return NULL;
297
}
298
 
299
/* Operand support.  */
300
 
301
/* Lookup an operand by its name.
302
   Returns NULL if NAME is not supported by the currently selected
303
   mach/isa.  */
304
 
305
const CGEN_OPERAND *
306
cgen_operand_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
307
{
308
  unsigned int i;
309
  const CGEN_OPERAND **op = cd->operand_table.entries;
310
 
311
  for (i = 0; i < cd->operand_table.num_entries; ++i)
312
    if (op[i] && strcmp (name, op[i]->name) == 0)
313
      return op[i];
314
 
315
  return NULL;
316
}
317
 
318
/* Lookup an operand by its number.
319
   Operands are enumerated, however it may be possible to add some
320
   at runtime, thus OPNUM is not an enum type but rather an int.
321
   Returns NULL if OPNUM is not supported by the currently selected
322
   mach/isa.  */
323
 
324
const CGEN_OPERAND *
325
cgen_operand_lookup_by_num (CGEN_CPU_DESC cd, int opnum)
326
{
327
  return cd->operand_table.entries[opnum];
328
}
329
 
330
/* Instruction support.  */
331
 
332
/* Return number of instructions.  This includes any added at runtime.  */
333
 
334
int
335
cgen_insn_count (CGEN_CPU_DESC cd)
336
{
337
  int count = cd->insn_table.num_init_entries;
338
  CGEN_INSN_LIST *rt_insns = cd->insn_table.new_entries;
339
 
340
  for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
341
    ++count;
342
 
343
  return count;
344
}
345
 
346
/* Return number of macro-instructions.
347
   This includes any added at runtime.  */
348
 
349
int
350
cgen_macro_insn_count (CGEN_CPU_DESC cd)
351
{
352
  int count = cd->macro_insn_table.num_init_entries;
353
  CGEN_INSN_LIST *rt_insns = cd->macro_insn_table.new_entries;
354
 
355
  for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
356
    ++count;
357
 
358
  return count;
359
}
360
 
361
/* Cover function to read and properly byteswap an insn value.  */
362
 
363
CGEN_INSN_INT
364
cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length)
365
{
366
  int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
367
  int insn_chunk_bitsize = cd->insn_chunk_bitsize;
368
  CGEN_INSN_INT value = 0;
369
 
370
  if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
371
    {
372
      /* We need to divide up the incoming value into insn_chunk_bitsize-length
373
         segments, and endian-convert them, one at a time. */
374
      int i;
375
 
376
      /* Enforce divisibility. */
377
      if ((length % insn_chunk_bitsize) != 0)
378
        abort ();
379
 
380
      for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
381
        {
382
          int index;
383
          bfd_vma this_value;
384
          index = i; /* NB: not dependent on endianness; opposite of cgen_put_insn_value! */
385
          this_value = bfd_get_bits (& buf[index / 8], insn_chunk_bitsize, big_p);
386
          value = (value << insn_chunk_bitsize) | this_value;
387
        }
388
    }
389
  else
390
    {
391
      value = bfd_get_bits (buf, length, cd->insn_endian == CGEN_ENDIAN_BIG);
392
    }
393
 
394
  return value;
395
}
396
 
397
/* Cover function to store an insn value properly byteswapped.  */
398
 
399
void
400
cgen_put_insn_value (CGEN_CPU_DESC cd,
401
                     unsigned char *buf,
402
                     int length,
403
                     CGEN_INSN_INT value)
404
{
405
  int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
406
  int insn_chunk_bitsize = cd->insn_chunk_bitsize;
407
 
408
  if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
409
    {
410
      /* We need to divide up the incoming value into insn_chunk_bitsize-length
411
         segments, and endian-convert them, one at a time. */
412
      int i;
413
 
414
      /* Enforce divisibility. */
415
      if ((length % insn_chunk_bitsize) != 0)
416
        abort ();
417
 
418
      for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
419
        {
420
          int index;
421
          index = (length - insn_chunk_bitsize - i); /* NB: not dependent on endianness! */
422
          bfd_put_bits ((bfd_vma) value, & buf[index / 8], insn_chunk_bitsize, big_p);
423
          value >>= insn_chunk_bitsize;
424
        }
425
    }
426
  else
427
    {
428
      bfd_put_bits ((bfd_vma) value, buf, length, big_p);
429
    }
430
}
431
 
432
/* Look up instruction INSN_*_VALUE and extract its fields.
433
   INSN_INT_VALUE is used if CGEN_INT_INSN_P.
434
   Otherwise INSN_BYTES_VALUE is used.
435
   INSN, if non-null, is the insn table entry.
436
   Otherwise INSN_*_VALUE is examined to compute it.
437
   LENGTH is the bit length of INSN_*_VALUE if known, otherwise 0.
438
 
439
   If INSN != NULL, LENGTH must be valid.
440
   ALIAS_P is non-zero if alias insns are to be included in the search.
441
 
442
   The result is a pointer to the insn table entry, or NULL if the instruction
443
   wasn't recognized.  */
444
 
445
/* ??? Will need to be revisited for VLIW architectures.  */
446
 
447
const CGEN_INSN *
448
cgen_lookup_insn (CGEN_CPU_DESC cd,
449
                  const CGEN_INSN *insn,
450
                  CGEN_INSN_INT insn_int_value,
451
                  /* ??? CGEN_INSN_BYTES would be a nice type name to use here.  */
452
                  unsigned char *insn_bytes_value,
453
                  int length,
454
                  CGEN_FIELDS *fields,
455
                  int alias_p)
456
{
457
  unsigned char *buf;
458
  CGEN_INSN_INT base_insn;
459
  CGEN_EXTRACT_INFO ex_info;
460
  CGEN_EXTRACT_INFO *info;
461
 
462
  if (cd->int_insn_p)
463
    {
464
      info = NULL;
465
      buf = (unsigned char *) alloca (cd->max_insn_bitsize / 8);
466
      cgen_put_insn_value (cd, buf, length, insn_int_value);
467
      base_insn = insn_int_value;
468
    }
469
  else
470
    {
471
      info = &ex_info;
472
      ex_info.dis_info = NULL;
473
      ex_info.insn_bytes = insn_bytes_value;
474
      ex_info.valid = -1;
475
      buf = insn_bytes_value;
476
      base_insn = cgen_get_insn_value (cd, buf, length);
477
    }
478
 
479
  if (!insn)
480
    {
481
      const CGEN_INSN_LIST *insn_list;
482
 
483
      /* The instructions are stored in hash lists.
484
         Pick the first one and keep trying until we find the right one.  */
485
 
486
      insn_list = cgen_dis_lookup_insn (cd, (char *) buf, base_insn);
487
      while (insn_list != NULL)
488
        {
489
          insn = insn_list->insn;
490
 
491
          if (alias_p
492
              /* FIXME: Ensure ALIAS attribute always has same index.  */
493
              || ! CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
494
            {
495
              /* Basic bit mask must be correct.  */
496
              /* ??? May wish to allow target to defer this check until the
497
                 extract handler.  */
498
              if ((base_insn & CGEN_INSN_BASE_MASK (insn))
499
                  == CGEN_INSN_BASE_VALUE (insn))
500
                {
501
                  /* ??? 0 is passed for `pc' */
502
                  int elength = CGEN_EXTRACT_FN (cd, insn)
503
                    (cd, insn, info, base_insn, fields, (bfd_vma) 0);
504
                  if (elength > 0)
505
                    {
506
                      /* sanity check */
507
                      if (length != 0 && length != elength)
508
                        abort ();
509
                      return insn;
510
                    }
511
                }
512
            }
513
 
514
          insn_list = insn_list->next;
515
        }
516
    }
517
  else
518
    {
519
      /* Sanity check: can't pass an alias insn if ! alias_p.  */
520
      if (! alias_p
521
          && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
522
        abort ();
523
      /* Sanity check: length must be correct.  */
524
      if (length != CGEN_INSN_BITSIZE (insn))
525
        abort ();
526
 
527
      /* ??? 0 is passed for `pc' */
528
      length = CGEN_EXTRACT_FN (cd, insn)
529
        (cd, insn, info, base_insn, fields, (bfd_vma) 0);
530
      /* Sanity check: must succeed.
531
         Could relax this later if it ever proves useful.  */
532
      if (length == 0)
533
        abort ();
534
      return insn;
535
    }
536
 
537
  return NULL;
538
}
539
 
540
/* Fill in the operand instances used by INSN whose operands are FIELDS.
541
   INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled
542
   in.  */
543
 
544
void
545
cgen_get_insn_operands (CGEN_CPU_DESC cd,
546
                        const CGEN_INSN *insn,
547
                        const CGEN_FIELDS *fields,
548
                        int *indices)
549
{
550
  const CGEN_OPINST *opinst;
551
  int i;
552
 
553
  if (insn->opinst == NULL)
554
    abort ();
555
  for (i = 0, opinst = insn->opinst; opinst->type != CGEN_OPINST_END; ++i, ++opinst)
556
    {
557
      enum cgen_operand_type op_type = opinst->op_type;
558
      if (op_type == CGEN_OPERAND_NIL)
559
        indices[i] = opinst->index;
560
      else
561
        indices[i] = (*cd->get_int_operand) (cd, op_type, fields);
562
    }
563
}
564
 
565
/* Cover function to cgen_get_insn_operands when either INSN or FIELDS
566
   isn't known.
567
   The INSN, INSN_*_VALUE, and LENGTH arguments are passed to
568
   cgen_lookup_insn unchanged.
569
   INSN_INT_VALUE is used if CGEN_INT_INSN_P.
570
   Otherwise INSN_BYTES_VALUE is used.
571
 
572
   The result is the insn table entry or NULL if the instruction wasn't
573
   recognized.  */
574
 
575
const CGEN_INSN *
576
cgen_lookup_get_insn_operands (CGEN_CPU_DESC cd,
577
                               const CGEN_INSN *insn,
578
                               CGEN_INSN_INT insn_int_value,
579
                               /* ??? CGEN_INSN_BYTES would be a nice type name to use here.  */
580
                               unsigned char *insn_bytes_value,
581
                               int length,
582
                               int *indices,
583
                               CGEN_FIELDS *fields)
584
{
585
  /* Pass non-zero for ALIAS_P only if INSN != NULL.
586
     If INSN == NULL, we want a real insn.  */
587
  insn = cgen_lookup_insn (cd, insn, insn_int_value, insn_bytes_value,
588
                           length, fields, insn != NULL);
589
  if (! insn)
590
    return NULL;
591
 
592
  cgen_get_insn_operands (cd, insn, fields, indices);
593
  return insn;
594
}
595
 
596
/* Allow signed overflow of instruction fields.  */
597
void
598
cgen_set_signed_overflow_ok (CGEN_CPU_DESC cd)
599
{
600
  cd->signed_overflow_ok_p = 1;
601
}
602
 
603
/* Generate an error message if a signed field in an instruction overflows.  */
604
void
605
cgen_clear_signed_overflow_ok (CGEN_CPU_DESC cd)
606
{
607
  cd->signed_overflow_ok_p = 0;
608
}
609
 
610
/* Will an error message be generated if a signed field in an instruction overflows ? */
611
unsigned int
612
cgen_signed_overflow_ok_p (CGEN_CPU_DESC cd)
613
{
614
  return cd->signed_overflow_ok_p;
615
}

powered by: WebSVN 2.1.0

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