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