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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [opcodes/] [cgen-opc.c] - Blame information for rev 1780

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

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

powered by: WebSVN 2.1.0

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