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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1181 sfurman
/* CGEN generic disassembler support code.
2
 
3
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
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 "bfd.h"
27
#include "symcat.h"
28
#include "opcode/cgen.h"
29
 
30
static CGEN_INSN_LIST *  hash_insn_array      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, int, int, CGEN_INSN_LIST **, CGEN_INSN_LIST *));
31
static CGEN_INSN_LIST *  hash_insn_list       PARAMS ((CGEN_CPU_DESC, const CGEN_INSN_LIST *, CGEN_INSN_LIST **, CGEN_INSN_LIST *));
32
static void              build_dis_hash_table PARAMS ((CGEN_CPU_DESC));
33
static int               count_decodable_bits PARAMS ((const CGEN_INSN *));
34
static void              add_insn_to_hash_chain PARAMS ((CGEN_INSN_LIST *,
35
                                                         const CGEN_INSN *,
36
                                                         CGEN_INSN_LIST **,
37
                                                         unsigned int));
38
 
39
/* Return the number of decodable bits in this insn.  */
40
static int
41
count_decodable_bits (insn)
42
  const CGEN_INSN *insn;
43
{
44
  unsigned mask = CGEN_INSN_BASE_MASK (insn);
45
  int bits = 0;
46
  int m;
47
  for (m = 1; m != 0; m <<= 1)
48
    {
49
      if (mask & m)
50
        ++bits;
51
    }
52
  return bits;
53
}
54
 
55
/* Add an instruction to the hash chain.  */
56
static void
57
add_insn_to_hash_chain (hentbuf, insn, htable, hash)
58
     CGEN_INSN_LIST *hentbuf;
59
     const CGEN_INSN *insn;
60
     CGEN_INSN_LIST **htable;
61
     unsigned int hash;
62
{
63
  CGEN_INSN_LIST *current_buf;
64
  CGEN_INSN_LIST *previous_buf;
65
  int insn_decodable_bits;
66
 
67
  /* Add insns sorted by the number of decodable bits, in decreasing order.
68
     This ensures that any insn which is a special case of another will be
69
     checked first.  */
70
  insn_decodable_bits = count_decodable_bits (insn);
71
  previous_buf = NULL;
72
  for (current_buf = htable[hash]; current_buf != NULL;
73
       current_buf = current_buf->next)
74
    {
75
      int current_decodable_bits = count_decodable_bits (current_buf->insn);
76
      if (insn_decodable_bits >= current_decodable_bits)
77
        break;
78
      previous_buf = current_buf;
79
    }
80
 
81
  /* Now insert the new insn.  */
82
  hentbuf->insn = insn;
83
  hentbuf->next = current_buf;
84
  if (previous_buf == NULL)
85
    htable[hash] = hentbuf;
86
  else
87
    previous_buf->next = hentbuf;
88
}
89
 
90
/* Subroutine of build_dis_hash_table to add INSNS to the hash table.
91
 
92
   COUNT is the number of elements in INSNS.
93
   ENTSIZE is sizeof (CGEN_IBASE) for the target.
94
   ??? No longer used but leave in for now.
95
   HTABLE points to the hash table.
96
   HENTBUF is a pointer to sufficiently large buffer of hash entries.
97
   The result is a pointer to the next entry to use.
98
 
99
   The table is scanned backwards as additions are made to the front of the
100
   list and we want earlier ones to be prefered.  */
101
 
102
static CGEN_INSN_LIST *
103
hash_insn_array (cd, insns, count, entsize, htable, hentbuf)
104
     CGEN_CPU_DESC cd;
105
     const CGEN_INSN * insns;
106
     int count;
107
     int entsize ATTRIBUTE_UNUSED;
108
     CGEN_INSN_LIST ** htable;
109
     CGEN_INSN_LIST * hentbuf;
110
{
111
  int big_p = CGEN_CPU_ENDIAN (cd) == CGEN_ENDIAN_BIG;
112
  int i;
113
 
114
  for (i = count - 1; i >= 0; --i, ++hentbuf)
115
    {
116
      unsigned int hash;
117
      char buf [4];
118
      unsigned long value;
119
      const CGEN_INSN *insn = &insns[i];
120
 
121
      if (! (* cd->dis_hash_p) (insn))
122
        continue;
123
 
124
      /* We don't know whether the target uses the buffer or the base insn
125
         to hash on, so set both up.  */
126
 
127
      value = CGEN_INSN_BASE_VALUE (insn);
128
      bfd_put_bits ((bfd_vma) value,
129
                    buf,
130
                    CGEN_INSN_MASK_BITSIZE (insn),
131
                    big_p);
132
      hash = (* cd->dis_hash) (buf, value);
133
      add_insn_to_hash_chain (hentbuf, insn, htable, hash);
134
    }
135
 
136
  return hentbuf;
137
}
138
 
139
/* Subroutine of build_dis_hash_table to add INSNS to the hash table.
140
   This function is identical to hash_insn_array except the insns are
141
   in a list.  */
142
 
143
static CGEN_INSN_LIST *
144
hash_insn_list (cd, insns, htable, hentbuf)
145
     CGEN_CPU_DESC cd;
146
     const CGEN_INSN_LIST *insns;
147
     CGEN_INSN_LIST **htable;
148
     CGEN_INSN_LIST *hentbuf;
149
{
150
  int big_p = CGEN_CPU_ENDIAN (cd) == CGEN_ENDIAN_BIG;
151
  const CGEN_INSN_LIST *ilist;
152
 
153
  for (ilist = insns; ilist != NULL; ilist = ilist->next, ++ hentbuf)
154
    {
155
      unsigned int hash;
156
      char buf[4];
157
      unsigned long value;
158
 
159
      if (! (* cd->dis_hash_p) (ilist->insn))
160
        continue;
161
 
162
      /* We don't know whether the target uses the buffer or the base insn
163
         to hash on, so set both up.  */
164
 
165
      value = CGEN_INSN_BASE_VALUE (ilist->insn);
166
      bfd_put_bits((bfd_vma) value,
167
                   buf,
168
                   CGEN_INSN_MASK_BITSIZE (ilist->insn),
169
                   big_p);
170
      hash = (* cd->dis_hash) (buf, value);
171
      add_insn_to_hash_chain (hentbuf, ilist->insn, htable, hash);
172
    }
173
 
174
  return hentbuf;
175
}
176
 
177
/* Build the disassembler instruction hash table.  */
178
 
179
static void
180
build_dis_hash_table (cd)
181
     CGEN_CPU_DESC cd;
182
{
183
  int count = cgen_insn_count (cd) + cgen_macro_insn_count (cd);
184
  CGEN_INSN_TABLE *insn_table = & cd->insn_table;
185
  CGEN_INSN_TABLE *macro_insn_table = & cd->macro_insn_table;
186
  unsigned int hash_size = cd->dis_hash_size;
187
  CGEN_INSN_LIST *hash_entry_buf;
188
  CGEN_INSN_LIST **dis_hash_table;
189
  CGEN_INSN_LIST *dis_hash_table_entries;
190
 
191
  /* The space allocated for the hash table consists of two parts:
192
     the hash table and the hash lists.  */
193
 
194
  dis_hash_table = (CGEN_INSN_LIST **)
195
    xmalloc (hash_size * sizeof (CGEN_INSN_LIST *));
196
  memset (dis_hash_table, 0, hash_size * sizeof (CGEN_INSN_LIST *));
197
  dis_hash_table_entries = hash_entry_buf = (CGEN_INSN_LIST *)
198
    xmalloc (count * sizeof (CGEN_INSN_LIST));
199
 
200
  /* Add compiled in insns.
201
     Don't include the first one as it is a reserved entry.  */
202
  /* ??? It was the end of all hash chains, and also the special
203
     "invalid insn" marker.  May be able to do it differently now.  */
204
 
205
  hash_entry_buf = hash_insn_array (cd,
206
                                    insn_table->init_entries + 1,
207
                                    insn_table->num_init_entries - 1,
208
                                    insn_table->entry_size,
209
                                    dis_hash_table, hash_entry_buf);
210
 
211
  /* Add compiled in macro-insns.  */
212
 
213
  hash_entry_buf = hash_insn_array (cd, macro_insn_table->init_entries,
214
                                    macro_insn_table->num_init_entries,
215
                                    macro_insn_table->entry_size,
216
                                    dis_hash_table, hash_entry_buf);
217
 
218
  /* Add runtime added insns.
219
     Later added insns will be prefered over earlier ones.  */
220
 
221
  hash_entry_buf = hash_insn_list (cd, insn_table->new_entries,
222
                                   dis_hash_table, hash_entry_buf);
223
 
224
  /* Add runtime added macro-insns.  */
225
 
226
  hash_insn_list (cd, macro_insn_table->new_entries,
227
                  dis_hash_table, hash_entry_buf);
228
 
229
  cd->dis_hash_table = dis_hash_table;
230
  cd->dis_hash_table_entries = dis_hash_table_entries;
231
}
232
 
233
/* Return the first entry in the hash list for INSN.  */
234
 
235
CGEN_INSN_LIST *
236
cgen_dis_lookup_insn (cd, buf, value)
237
     CGEN_CPU_DESC cd;
238
     const char * buf;
239
     CGEN_INSN_INT value;
240
{
241
  unsigned int hash;
242
 
243
  if (cd->dis_hash_table == NULL)
244
    build_dis_hash_table (cd);
245
 
246
  hash = (* cd->dis_hash) (buf, value);
247
 
248
  return cd->dis_hash_table[hash];
249
}

powered by: WebSVN 2.1.0

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