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