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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 18 khays
/* CGEN generic assembler support code.
2
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of libopcodes.
6
 
7
   This library is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3, or (at your option)
10
   any later version.
11
 
12
   It is distributed in the hope that it will be useful, but WITHOUT
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15
   License for more details.
16
 
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
#include "opintl.h"
31
 
32
static CGEN_INSN_LIST *  hash_insn_array      (CGEN_CPU_DESC, const CGEN_INSN *, int, int, CGEN_INSN_LIST **, CGEN_INSN_LIST *);
33
static CGEN_INSN_LIST *  hash_insn_list       (CGEN_CPU_DESC, const CGEN_INSN_LIST *, CGEN_INSN_LIST **, CGEN_INSN_LIST *);
34
static void              build_asm_hash_table (CGEN_CPU_DESC);
35
 
36
/* Set the cgen_parse_operand_fn callback.  */
37
 
38
void
39
cgen_set_parse_operand_fn (CGEN_CPU_DESC cd, cgen_parse_operand_fn fn)
40
{
41
  cd->parse_operand_fn = fn;
42
}
43
 
44
/* Called whenever starting to parse an insn.  */
45
 
46
void
47
cgen_init_parse_operand (CGEN_CPU_DESC cd)
48
{
49
  /* This tells the callback to re-initialize.  */
50
  (void) (* cd->parse_operand_fn)
51
    (cd, CGEN_PARSE_OPERAND_INIT, NULL, 0, 0, NULL, NULL);
52
}
53
 
54
/* Subroutine of build_asm_hash_table to add INSNS to the hash table.
55
 
56
   COUNT is the number of elements in INSNS.
57
   ENTSIZE is sizeof (CGEN_IBASE) for the target.
58
   ??? No longer used but leave in for now.
59
   HTABLE points to the hash table.
60
   HENTBUF is a pointer to sufficiently large buffer of hash entries.
61
   The result is a pointer to the next entry to use.
62
 
63
   The table is scanned backwards as additions are made to the front of the
64
   list and we want earlier ones to be prefered.  */
65
 
66
static CGEN_INSN_LIST *
67
hash_insn_array (CGEN_CPU_DESC cd,
68
                 const CGEN_INSN *insns,
69
                 int count,
70
                 int entsize ATTRIBUTE_UNUSED,
71
                 CGEN_INSN_LIST **htable,
72
                 CGEN_INSN_LIST *hentbuf)
73
{
74
  int i;
75
 
76
  for (i = count - 1; i >= 0; --i, ++hentbuf)
77
    {
78
      unsigned int hash;
79
      const CGEN_INSN *insn = &insns[i];
80
 
81
      if (! (* cd->asm_hash_p) (insn))
82
        continue;
83
      hash = (* cd->asm_hash) (CGEN_INSN_MNEMONIC (insn));
84
      hentbuf->next = htable[hash];
85
      hentbuf->insn = insn;
86
      htable[hash] = hentbuf;
87
    }
88
 
89
  return hentbuf;
90
}
91
 
92
/* Subroutine of build_asm_hash_table to add INSNS to the hash table.
93
   This function is identical to hash_insn_array except the insns are
94
   in a list.  */
95
 
96
static CGEN_INSN_LIST *
97
hash_insn_list (CGEN_CPU_DESC cd,
98
                const CGEN_INSN_LIST *insns,
99
                CGEN_INSN_LIST **htable,
100
                CGEN_INSN_LIST *hentbuf)
101
{
102
  const CGEN_INSN_LIST *ilist;
103
 
104
  for (ilist = insns; ilist != NULL; ilist = ilist->next, ++ hentbuf)
105
    {
106
      unsigned int hash;
107
 
108
      if (! (* cd->asm_hash_p) (ilist->insn))
109
        continue;
110
      hash = (* cd->asm_hash) (CGEN_INSN_MNEMONIC (ilist->insn));
111
      hentbuf->next = htable[hash];
112
      hentbuf->insn = ilist->insn;
113
      htable[hash] = hentbuf;
114
    }
115
 
116
  return hentbuf;
117
}
118
 
119
/* Build the assembler instruction hash table.  */
120
 
121
static void
122
build_asm_hash_table (CGEN_CPU_DESC cd)
123
{
124
  int count = cgen_insn_count (cd) + cgen_macro_insn_count (cd);
125
  CGEN_INSN_TABLE *insn_table = &cd->insn_table;
126
  CGEN_INSN_TABLE *macro_insn_table = &cd->macro_insn_table;
127
  unsigned int hash_size = cd->asm_hash_size;
128
  CGEN_INSN_LIST *hash_entry_buf;
129
  CGEN_INSN_LIST **asm_hash_table;
130
  CGEN_INSN_LIST *asm_hash_table_entries;
131
 
132
  /* The space allocated for the hash table consists of two parts:
133
     the hash table and the hash lists.  */
134
 
135
  asm_hash_table = (CGEN_INSN_LIST **)
136
    xmalloc (hash_size * sizeof (CGEN_INSN_LIST *));
137
  memset (asm_hash_table, 0, hash_size * sizeof (CGEN_INSN_LIST *));
138
  asm_hash_table_entries = hash_entry_buf = (CGEN_INSN_LIST *)
139
    xmalloc (count * sizeof (CGEN_INSN_LIST));
140
 
141
  /* Add compiled in insns.
142
     Don't include the first one as it is a reserved entry.  */
143
  /* ??? It was the end of all hash chains, and also the special
144
     "invalid insn" marker.  May be able to do it differently now.  */
145
 
146
  hash_entry_buf = hash_insn_array (cd,
147
                                    insn_table->init_entries + 1,
148
                                    insn_table->num_init_entries - 1,
149
                                    insn_table->entry_size,
150
                                    asm_hash_table, hash_entry_buf);
151
 
152
  /* Add compiled in macro-insns.  */
153
 
154
  hash_entry_buf = hash_insn_array (cd, macro_insn_table->init_entries,
155
                                    macro_insn_table->num_init_entries,
156
                                    macro_insn_table->entry_size,
157
                                    asm_hash_table, hash_entry_buf);
158
 
159
  /* Add runtime added insns.
160
     Later added insns will be prefered over earlier ones.  */
161
 
162
  hash_entry_buf = hash_insn_list (cd, insn_table->new_entries,
163
                                   asm_hash_table, hash_entry_buf);
164
 
165
  /* Add runtime added macro-insns.  */
166
 
167
  hash_insn_list (cd, macro_insn_table->new_entries,
168
                  asm_hash_table, hash_entry_buf);
169
 
170
  cd->asm_hash_table = asm_hash_table;
171
  cd->asm_hash_table_entries = asm_hash_table_entries;
172
}
173
 
174
/* Return the first entry in the hash list for INSN.  */
175
 
176
CGEN_INSN_LIST *
177
cgen_asm_lookup_insn (CGEN_CPU_DESC cd, const char *insn)
178
{
179
  unsigned int hash;
180
 
181
  if (cd->asm_hash_table == NULL)
182
    build_asm_hash_table (cd);
183
 
184
  hash = (* cd->asm_hash) (insn);
185
  return cd->asm_hash_table[hash];
186
}
187
 
188
/* Keyword parser.
189
   The result is NULL upon success or an error message.
190
   If successful, *STRP is updated to point passed the keyword.
191
 
192
   ??? At present we have a static notion of how to pick out a keyword.
193
   Later we can allow a target to customize this if necessary [say by
194
   recording something in the keyword table].  */
195
 
196
const char *
197
cgen_parse_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
198
                    const char **strp,
199
                    CGEN_KEYWORD *keyword_table,
200
                    long *valuep)
201
{
202
  const CGEN_KEYWORD_ENTRY *ke;
203
  char buf[256];
204
  const char *p,*start;
205
 
206
  if (keyword_table->name_hash_table == NULL)
207
    (void) cgen_keyword_search_init (keyword_table, NULL);
208
 
209
  p = start = *strp;
210
 
211
  /* Allow any first character.  This is to make life easier for
212
     the fairly common case of suffixes, eg. 'ld.b.w', where the first
213
     character of the suffix ('.') is special.  */
214
  if (*p)
215
    ++p;
216
 
217
  /* Allow letters, digits, and any special characters.  */
218
  while (((p - start) < (int) sizeof (buf))
219
         && *p
220
         && (ISALNUM (*p)
221
             || *p == '_'
222
             || strchr (keyword_table->nonalpha_chars, *p)))
223
    ++p;
224
 
225
  if (p - start >= (int) sizeof (buf))
226
    {
227
      /* All non-empty CGEN keywords can fit into BUF.  The only thing
228
         we can match here is the empty keyword.  */
229
      buf[0] = 0;
230
    }
231
  else
232
    {
233
      memcpy (buf, start, p - start);
234
      buf[p - start] = 0;
235
    }
236
 
237
  ke = cgen_keyword_lookup_name (keyword_table, buf);
238
 
239
  if (ke != NULL)
240
    {
241
      *valuep = ke->value;
242
      /* Don't advance pointer if we recognized the null keyword.  */
243
      if (ke->name[0] != 0)
244
        *strp = p;
245
      return NULL;
246
    }
247
 
248
  return "unrecognized keyword/register name";
249
}
250
 
251
/* Parse a small signed integer parser.
252
   ??? VALUEP is not a bfd_vma * on purpose, though this is confusing.
253
   Note that if the caller expects a bfd_vma result, it should call
254
   cgen_parse_address.  */
255
 
256
const char *
257
cgen_parse_signed_integer (CGEN_CPU_DESC cd,
258
                           const char **strp,
259
                           int opindex,
260
                           long *valuep)
261
{
262
  bfd_vma value;
263
  enum cgen_parse_operand_result result;
264
  const char *errmsg;
265
 
266
  errmsg = (* cd->parse_operand_fn)
267
    (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE,
268
     &result, &value);
269
  /* FIXME: Examine `result'.  */
270
  if (!errmsg)
271
    *valuep = value;
272
  return errmsg;
273
}
274
 
275
/* Parse a small unsigned integer parser.
276
   ??? VALUEP is not a bfd_vma * on purpose, though this is confusing.
277
   Note that if the caller expects a bfd_vma result, it should call
278
   cgen_parse_address.  */
279
 
280
const char *
281
cgen_parse_unsigned_integer (CGEN_CPU_DESC cd,
282
                             const char **strp,
283
                             int opindex,
284
                             unsigned long *valuep)
285
{
286
  bfd_vma value;
287
  enum cgen_parse_operand_result result;
288
  const char *errmsg;
289
 
290
  errmsg = (* cd->parse_operand_fn)
291
    (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE,
292
     &result, &value);
293
  /* FIXME: Examine `result'.  */
294
  if (!errmsg)
295
    *valuep = value;
296
  return errmsg;
297
}
298
 
299
/* Address parser.  */
300
 
301
const char *
302
cgen_parse_address (CGEN_CPU_DESC cd,
303
                    const char **strp,
304
                    int opindex,
305
                    int opinfo,
306
                    enum cgen_parse_operand_result *resultp,
307
                    bfd_vma *valuep)
308
{
309
  bfd_vma value;
310
  enum cgen_parse_operand_result result_type;
311
  const char *errmsg;
312
 
313
  errmsg = (* cd->parse_operand_fn)
314
    (cd, CGEN_PARSE_OPERAND_ADDRESS, strp, opindex, opinfo,
315
     &result_type, &value);
316
  /* FIXME: Examine `result'.  */
317
  if (!errmsg)
318
    {
319
      if (resultp != NULL)
320
        *resultp = result_type;
321
      *valuep = value;
322
    }
323
  return errmsg;
324
}
325
 
326
/* Signed integer validation routine.  */
327
 
328
const char *
329
cgen_validate_signed_integer (long value, long min, long max)
330
{
331
  if (value < min || value > max)
332
    {
333
      static char buf[100];
334
 
335
      /* xgettext:c-format */
336
      sprintf (buf, _("operand out of range (%ld not between %ld and %ld)"),
337
                      value, min, max);
338
      return buf;
339
    }
340
 
341
  return NULL;
342
}
343
 
344
/* Unsigned integer validation routine.
345
   Supplying `min' here may seem unnecessary, but we also want to handle
346
   cases where min != 0 (and max > LONG_MAX).  */
347
 
348
const char *
349
cgen_validate_unsigned_integer (unsigned long value,
350
                                unsigned long min,
351
                                unsigned long max)
352
{
353
  if (value < min || value > max)
354
    {
355
      static char buf[100];
356
 
357
      /* xgettext:c-format */
358
      sprintf (buf, _("operand out of range (%lu not between %lu and %lu)"),
359
               value, min, max);
360
      return buf;
361
    }
362
 
363
  return NULL;
364
}

powered by: WebSVN 2.1.0

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