xref: /openbsd/gnu/usr.bin/binutils/bfd/xtensa-isa.c (revision 7b36286a)
1 /* Configurable Xtensa ISA support.
2    Copyright 2003 Free Software Foundation, Inc.
3 
4    This file is part of BFD, the Binary File Descriptor library.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <string.h>
24 
25 #include "xtensa-isa.h"
26 #include "xtensa-isa-internal.h"
27 
28 xtensa_isa xtensa_default_isa = NULL;
29 
30 static int
31 opname_lookup_compare (const void *v1, const void *v2)
32 {
33   opname_lookup_entry *e1 = (opname_lookup_entry *)v1;
34   opname_lookup_entry *e2 = (opname_lookup_entry *)v2;
35 
36   return strcmp (e1->key, e2->key);
37 }
38 
39 
40 xtensa_isa
41 xtensa_isa_init (void)
42 {
43   xtensa_isa isa;
44   int mod;
45 
46   isa = xtensa_load_isa (0);
47   if (isa == 0)
48     {
49       fprintf (stderr, "Failed to initialize Xtensa base ISA module\n");
50       return NULL;
51     }
52 
53   for (mod = 1; xtensa_isa_modules[mod].get_num_opcodes_fn; mod++)
54     {
55       if (!xtensa_extend_isa (isa, mod))
56 	{
57 	  fprintf (stderr, "Failed to initialize Xtensa TIE ISA module\n");
58 	  return NULL;
59 	}
60     }
61 
62   return isa;
63 }
64 
65 /* ISA information.  */
66 
67 static int
68 xtensa_check_isa_config (xtensa_isa_internal *isa,
69 			 struct config_struct *config_table)
70 {
71   int i, j;
72 
73   if (!config_table)
74     {
75       fprintf (stderr, "Error: Empty configuration table in ISA DLL\n");
76       return 0;
77     }
78 
79   /* For the first module, save a pointer to the table and record the
80      specified endianness and availability of the density option.  */
81 
82   if (isa->num_modules == 0)
83     {
84       int found_memory_order = 0;
85 
86       isa->config = config_table;
87       isa->has_density = 1;  /* Default to have density option.  */
88 
89       for (i = 0; config_table[i].param_name; i++)
90 	{
91 	  if (!strcmp (config_table[i].param_name, "IsaMemoryOrder"))
92 	    {
93 	      isa->is_big_endian =
94 		(strcmp (config_table[i].param_value, "BigEndian") == 0);
95 	      found_memory_order = 1;
96 	    }
97 	  if (!strcmp (config_table[i].param_name, "IsaUseDensityInstruction"))
98 	    {
99 	      isa->has_density = atoi (config_table[i].param_value);
100 	    }
101 	}
102       if (!found_memory_order)
103 	{
104 	  fprintf (stderr, "Error: \"IsaMemoryOrder\" missing from "
105 		   "configuration table in ISA DLL\n");
106 	  return 0;
107 	}
108 
109       return 1;
110     }
111 
112   /* For subsequent modules, check that the parameters match.  Note: This
113      code is sufficient to handle the current model where there are never
114      more than 2 modules; we might at some point want to handle cases where
115      module N > 0 specifies some parameters not included in the base table,
116      and we would then add those to isa->config so that subsequent modules
117      would check against them. */
118 
119   for (i = 0; config_table[i].param_name; i++)
120     {
121       for (j = 0; isa->config[j].param_name; j++)
122 	{
123 	  if (!strcmp (config_table[i].param_name, isa->config[j].param_name))
124 	    {
125 	      int mismatch;
126 	      if (!strcmp (config_table[i].param_name, "IsaCoprocessorCount"))
127 		{
128 		  /* Only require the coprocessor count to be <= the base.  */
129 		  int tiecnt = atoi (config_table[i].param_value);
130 		  int basecnt = atoi (isa->config[j].param_value);
131 		  mismatch = (tiecnt > basecnt);
132 		}
133 	      else
134 		mismatch = strcmp (config_table[i].param_value,
135 				   isa->config[j].param_value);
136 	      if (mismatch)
137 		{
138 #define MISMATCH_MESSAGE \
139 "Error: Configuration mismatch in the \"%s\" parameter:\n\
140 the configuration used when the TIE file was compiled had a value of\n\
141 \"%s\", while the current configuration has a value of\n\
142 \"%s\". Please rerun the TIE compiler with a matching\n\
143 configuration.\n"
144 		  fprintf (stderr, MISMATCH_MESSAGE,
145 			   config_table[i].param_name,
146 			   config_table[i].param_value,
147 			   isa->config[j].param_value);
148 		  return 0;
149 		}
150 	      break;
151 	    }
152 	}
153     }
154 
155   return 1;
156 }
157 
158 
159 static int
160 xtensa_add_isa (xtensa_isa_internal *isa, libisa_module_specifier libisa)
161 {
162   int (*get_num_opcodes_fn) (void);
163   struct config_struct *(*get_config_table_fn) (void);
164   xtensa_opcode_internal **(*get_opcodes_fn) (void);
165   int (*decode_insn_fn) (const xtensa_insnbuf);
166   xtensa_opcode_internal **opcodes;
167   int opc, insn_size, prev_num_opcodes, new_num_opcodes, this_module;
168 
169   get_num_opcodes_fn = xtensa_isa_modules[libisa].get_num_opcodes_fn;
170   get_opcodes_fn = xtensa_isa_modules[libisa].get_opcodes_fn;
171   decode_insn_fn = xtensa_isa_modules[libisa].decode_insn_fn;
172   get_config_table_fn = xtensa_isa_modules[libisa].get_config_table_fn;
173 
174   if (!get_num_opcodes_fn || !get_opcodes_fn || !decode_insn_fn
175       || (!get_config_table_fn && isa->num_modules == 0))
176     return 0;
177 
178   if (get_config_table_fn
179       && !xtensa_check_isa_config (isa, get_config_table_fn ()))
180     return 0;
181 
182   prev_num_opcodes = isa->num_opcodes;
183   new_num_opcodes = (*get_num_opcodes_fn) ();
184 
185   isa->num_opcodes += new_num_opcodes;
186   isa->opcode_table = (xtensa_opcode_internal **)
187     realloc (isa->opcode_table, isa->num_opcodes *
188 	     sizeof (xtensa_opcode_internal *));
189   isa->opname_lookup_table = (opname_lookup_entry *)
190     realloc (isa->opname_lookup_table, isa->num_opcodes *
191 	     sizeof (opname_lookup_entry));
192 
193   opcodes = (*get_opcodes_fn) ();
194 
195   insn_size = isa->insn_size;
196   for (opc = 0; opc < new_num_opcodes; opc++)
197     {
198       xtensa_opcode_internal *intopc = opcodes[opc];
199       int newopc = prev_num_opcodes + opc;
200       isa->opcode_table[newopc] = intopc;
201       isa->opname_lookup_table[newopc].key = intopc->name;
202       isa->opname_lookup_table[newopc].opcode = newopc;
203       if (intopc->length > insn_size)
204 	insn_size = intopc->length;
205     }
206 
207   isa->insn_size = insn_size;
208   isa->insnbuf_size = ((isa->insn_size + sizeof (xtensa_insnbuf_word) - 1) /
209 		       sizeof (xtensa_insnbuf_word));
210 
211   qsort (isa->opname_lookup_table, isa->num_opcodes,
212 	 sizeof (opname_lookup_entry), opname_lookup_compare);
213 
214   /* Check for duplicate opcode names.  */
215   for (opc = 1; opc < isa->num_opcodes; opc++)
216     {
217       if (!opname_lookup_compare (&isa->opname_lookup_table[opc-1],
218 				  &isa->opname_lookup_table[opc]))
219 	{
220 	  fprintf (stderr, "Error: Duplicate TIE opcode \"%s\"\n",
221 		   isa->opname_lookup_table[opc].key);
222 	  return 0;
223 	}
224     }
225 
226   this_module = isa->num_modules;
227   isa->num_modules += 1;
228 
229   isa->module_opcode_base = (int *) realloc (isa->module_opcode_base,
230 					     isa->num_modules * sizeof (int));
231   isa->module_decode_fn = (xtensa_insn_decode_fn *)
232     realloc (isa->module_decode_fn, isa->num_modules *
233 	     sizeof (xtensa_insn_decode_fn));
234 
235   isa->module_opcode_base[this_module] = prev_num_opcodes;
236   isa->module_decode_fn[this_module] = decode_insn_fn;
237 
238   xtensa_default_isa = isa;
239 
240   return 1;	/* Library was successfully added.  */
241 }
242 
243 
244 xtensa_isa
245 xtensa_load_isa (libisa_module_specifier libisa)
246 {
247   xtensa_isa_internal *isa;
248 
249   isa = (xtensa_isa_internal *) malloc (sizeof (xtensa_isa_internal));
250   memset (isa, 0, sizeof (xtensa_isa_internal));
251   if (!xtensa_add_isa (isa, libisa))
252     {
253       xtensa_isa_free (isa);
254       return NULL;
255     }
256   return (xtensa_isa) isa;
257 }
258 
259 
260 int
261 xtensa_extend_isa (xtensa_isa isa, libisa_module_specifier libisa)
262 {
263   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
264   return xtensa_add_isa (intisa, libisa);
265 }
266 
267 
268 void
269 xtensa_isa_free (xtensa_isa isa)
270 {
271   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
272   if (intisa->opcode_table)
273     free (intisa->opcode_table);
274   if (intisa->opname_lookup_table)
275     free (intisa->opname_lookup_table);
276   if (intisa->module_opcode_base)
277     free (intisa->module_opcode_base);
278   if (intisa->module_decode_fn)
279     free (intisa->module_decode_fn);
280   free (intisa);
281 }
282 
283 
284 int
285 xtensa_insn_maxlength (xtensa_isa isa)
286 {
287   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
288   return intisa->insn_size;
289 }
290 
291 
292 int
293 xtensa_insnbuf_size (xtensa_isa isa)
294 {
295   xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
296   return intisa->insnbuf_size;
297 }
298 
299 
300 int
301 xtensa_num_opcodes (xtensa_isa isa)
302 {
303   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
304   return intisa->num_opcodes;
305 }
306 
307 
308 xtensa_opcode
309 xtensa_opcode_lookup (xtensa_isa isa, const char *opname)
310 {
311   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
312   opname_lookup_entry entry, *result;
313 
314   entry.key = opname;
315   result = bsearch (&entry, intisa->opname_lookup_table, intisa->num_opcodes,
316 		    sizeof (opname_lookup_entry), opname_lookup_compare);
317   if (!result) return XTENSA_UNDEFINED;
318   return result->opcode;
319 }
320 
321 
322 xtensa_opcode
323 xtensa_decode_insn (xtensa_isa isa, const xtensa_insnbuf insn)
324 {
325   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
326   int n, opc;
327   for (n = 0; n < intisa->num_modules; n++) {
328     opc = (intisa->module_decode_fn[n]) (insn);
329     if (opc != XTENSA_UNDEFINED)
330       return intisa->module_opcode_base[n] + opc;
331   }
332   return XTENSA_UNDEFINED;
333 }
334 
335 
336 /* Opcode information.  */
337 
338 void
339 xtensa_encode_insn (xtensa_isa isa, xtensa_opcode opc, xtensa_insnbuf insn)
340 {
341   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
342   xtensa_insnbuf template = intisa->opcode_table[opc]->template();
343   int len = intisa->opcode_table[opc]->length;
344   int n;
345 
346   /* Convert length to 32-bit words.  */
347   len = (len + 3) / 4;
348 
349   /* Copy the template.  */
350   for (n = 0; n < len; n++)
351     insn[n] = template[n];
352 
353   /* Fill any unused buffer space with zeros.  */
354   for ( ; n < intisa->insnbuf_size; n++)
355     insn[n] = 0;
356 }
357 
358 
359 const char *
360 xtensa_opcode_name (xtensa_isa isa, xtensa_opcode opc)
361 {
362   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
363   return intisa->opcode_table[opc]->name;
364 }
365 
366 
367 int
368 xtensa_insn_length (xtensa_isa isa, xtensa_opcode opc)
369 {
370   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
371   return intisa->opcode_table[opc]->length;
372 }
373 
374 
375 int
376 xtensa_insn_length_from_first_byte (xtensa_isa isa, char first_byte)
377 {
378   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
379   int is_density = (first_byte & (intisa->is_big_endian ? 0x80 : 0x08)) != 0;
380   return (intisa->has_density && is_density ? 2 : 3);
381 }
382 
383 
384 int
385 xtensa_num_operands (xtensa_isa isa, xtensa_opcode opc)
386 {
387   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
388   return intisa->opcode_table[opc]->iclass->num_operands;
389 }
390 
391 
392 xtensa_operand
393 xtensa_get_operand (xtensa_isa isa, xtensa_opcode opc, int opnd)
394 {
395   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
396   xtensa_iclass_internal *iclass = intisa->opcode_table[opc]->iclass;
397   if (opnd >= iclass->num_operands)
398     return NULL;
399   return (xtensa_operand) iclass->operands[opnd];
400 }
401 
402 
403 /* Operand information.  */
404 
405 char *
406 xtensa_operand_kind (xtensa_operand opnd)
407 {
408   xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
409   return intop->operand_kind;
410 }
411 
412 
413 char
414 xtensa_operand_inout (xtensa_operand opnd)
415 {
416   xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
417   return intop->inout;
418 }
419 
420 
421 uint32
422 xtensa_operand_get_field (xtensa_operand opnd, const xtensa_insnbuf insn)
423 {
424   xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
425   return (*intop->get_field) (insn);
426 }
427 
428 
429 void
430 xtensa_operand_set_field (xtensa_operand opnd, xtensa_insnbuf insn, uint32 val)
431 {
432   xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
433   return (*intop->set_field) (insn, val);
434 }
435 
436 
437 xtensa_encode_result
438 xtensa_operand_encode (xtensa_operand opnd, uint32 *valp)
439 {
440   xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
441   return (*intop->encode) (valp);
442 }
443 
444 
445 uint32
446 xtensa_operand_decode (xtensa_operand opnd, uint32 val)
447 {
448   xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
449   return (*intop->decode) (val);
450 }
451 
452 
453 int
454 xtensa_operand_isPCRelative (xtensa_operand opnd)
455 {
456   xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
457   return intop->isPCRelative;
458 }
459 
460 
461 uint32
462 xtensa_operand_do_reloc (xtensa_operand opnd, uint32 addr, uint32 pc)
463 {
464   xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
465   if (!intop->isPCRelative)
466     return addr;
467   return (*intop->do_reloc) (addr, pc);
468 }
469 
470 
471 uint32
472 xtensa_operand_undo_reloc (xtensa_operand opnd, uint32 offset, uint32 pc)
473 {
474   xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
475   if (!intop->isPCRelative)
476     return offset;
477   return (*intop->undo_reloc) (offset, pc);
478 }
479 
480 
481 /* Instruction buffers.  */
482 
483 xtensa_insnbuf
484 xtensa_insnbuf_alloc (xtensa_isa isa)
485 {
486   return (xtensa_insnbuf) malloc (xtensa_insnbuf_size (isa) *
487 				  sizeof (xtensa_insnbuf_word));
488 }
489 
490 
491 void
492 xtensa_insnbuf_free (xtensa_insnbuf buf)
493 {
494   free( buf );
495 }
496 
497 
498 /* Given <byte_index>, the index of a byte in a xtensa_insnbuf, our
499    internal representation of a xtensa instruction word, return the index of
500    its word and the bit index of its low order byte in the xtensa_insnbuf.  */
501 
502 static inline int
503 byte_to_word_index (int byte_index)
504 {
505   return byte_index / sizeof (xtensa_insnbuf_word);
506 }
507 
508 
509 static inline int
510 byte_to_bit_index (int byte_index)
511 {
512   return (byte_index & 0x3) * 8;
513 }
514 
515 
516 /* Copy an instruction in the 32 bit words pointed at by <insn> to characters
517    pointed at by <cp>.  This is more complicated than you might think because
518    we want 16 bit instructions in bytes 2,3 for big endian. This function
519    allows us to specify which byte in <insn> to start with and which way to
520    increment, allowing trivial implementation for both big and little endian.
521    And it seems to make pretty good code for both.  */
522 
523 void
524 xtensa_insnbuf_to_chars (xtensa_isa isa, const xtensa_insnbuf insn, char *cp)
525 {
526   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
527   int insn_size = xtensa_insn_maxlength (intisa);
528   int fence_post, start, increment, i, byte_count;
529   xtensa_opcode opc;
530 
531   if (intisa->is_big_endian)
532     {
533       start = insn_size - 1;
534       increment = -1;
535     }
536   else
537     {
538       start = 0;
539       increment = 1;
540     }
541 
542   /* Find the opcode; do nothing if the buffer does not contain a valid
543      instruction since we need to know how many bytes to copy.  */
544   opc = xtensa_decode_insn (isa, insn);
545   if (opc == XTENSA_UNDEFINED)
546     return;
547 
548   byte_count = xtensa_insn_length (isa, opc);
549   fence_post = start + (byte_count * increment);
550 
551   for (i = start; i != fence_post; i += increment, ++cp)
552     {
553       int word_inx = byte_to_word_index (i);
554       int bit_inx = byte_to_bit_index (i);
555 
556       *cp = (insn[word_inx] >> bit_inx) & 0xff;
557     }
558 }
559 
560 /* Inward conversion from byte stream to xtensa_insnbuf.  See
561    xtensa_insnbuf_to_chars for a discussion of why this is
562    complicated by endianness.  */
563 
564 void
565 xtensa_insnbuf_from_chars (xtensa_isa isa, xtensa_insnbuf insn, const char* cp)
566 {
567   xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
568   int insn_size = xtensa_insn_maxlength (intisa);
569   int fence_post, start, increment, i;
570 
571   if (intisa->is_big_endian)
572     {
573       start = insn_size - 1;
574       increment = -1;
575     }
576   else
577     {
578       start = 0;
579       increment = 1;
580     }
581 
582   fence_post = start + (insn_size * increment);
583   memset (insn, 0, xtensa_insnbuf_size (isa) * sizeof (xtensa_insnbuf_word));
584 
585   for ( i = start; i != fence_post; i += increment, ++cp )
586     {
587       int word_inx = byte_to_word_index (i);
588       int bit_inx = byte_to_bit_index (i);
589 
590       insn[word_inx] |= (*cp & 0xff) << bit_inx;
591     }
592 }
593 
594