2004-01-30 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / bfd / xtensa-isa.c
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
This page took 0.04305 seconds and 4 git commands to generate.