1 /* Configurable Xtensa ISA support.
2 Copyright 2003 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
22 #include <sys/types.h>
25 #include "xtensa-isa.h"
26 #include "xtensa-isa-internal.h"
28 xtensa_isa xtensa_default_isa
= NULL
;
31 opname_lookup_compare (const void *v1
, const void *v2
)
33 opname_lookup_entry
*e1
= (opname_lookup_entry
*)v1
;
34 opname_lookup_entry
*e2
= (opname_lookup_entry
*)v2
;
36 return strcmp (e1
->key
, e2
->key
);
41 xtensa_isa_init (void)
46 isa
= xtensa_load_isa (0);
49 fprintf (stderr
, "Failed to initialize Xtensa base ISA module\n");
53 for (mod
= 1; xtensa_isa_modules
[mod
].get_num_opcodes_fn
; mod
++)
55 if (!xtensa_extend_isa (isa
, mod
))
57 fprintf (stderr
, "Failed to initialize Xtensa TIE ISA module\n");
65 /* ISA information. */
68 xtensa_check_isa_config (xtensa_isa_internal
*isa
,
69 struct config_struct
*config_table
)
75 fprintf (stderr
, "Error: Empty configuration table in ISA DLL\n");
79 /* For the first module, save a pointer to the table and record the
80 specified endianness and availability of the density option. */
82 if (isa
->num_modules
== 0)
84 int found_memory_order
= 0;
86 isa
->config
= config_table
;
87 isa
->has_density
= 1; /* Default to have density option. */
89 for (i
= 0; config_table
[i
].param_name
; i
++)
91 if (!strcmp (config_table
[i
].param_name
, "IsaMemoryOrder"))
94 (strcmp (config_table
[i
].param_value
, "BigEndian") == 0);
95 found_memory_order
= 1;
97 if (!strcmp (config_table
[i
].param_name
, "IsaUseDensityInstruction"))
99 isa
->has_density
= atoi (config_table
[i
].param_value
);
102 if (!found_memory_order
)
104 fprintf (stderr
, "Error: \"IsaMemoryOrder\" missing from "
105 "configuration table in ISA DLL\n");
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. */
119 for (i
= 0; config_table
[i
].param_name
; i
++)
121 for (j
= 0; isa
->config
[j
].param_name
; j
++)
123 if (!strcmp (config_table
[i
].param_name
, isa
->config
[j
].param_name
))
126 if (!strcmp (config_table
[i
].param_name
, "IsaCoprocessorCount"))
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
);
134 mismatch
= strcmp (config_table
[i
].param_value
,
135 isa
->config
[j
].param_value
);
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\
144 fprintf (stderr
, MISMATCH_MESSAGE
,
145 config_table
[i
].param_name
,
146 config_table
[i
].param_value
,
147 isa
->config
[j
].param_value
);
160 xtensa_add_isa (xtensa_isa_internal
*isa
, libisa_module_specifier libisa
)
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
;
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
;
174 if (!get_num_opcodes_fn
|| !get_opcodes_fn
|| !decode_insn_fn
175 || (!get_config_table_fn
&& isa
->num_modules
== 0))
178 if (get_config_table_fn
179 && !xtensa_check_isa_config (isa
, get_config_table_fn ()))
182 prev_num_opcodes
= isa
->num_opcodes
;
183 new_num_opcodes
= (*get_num_opcodes_fn
) ();
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
));
193 opcodes
= (*get_opcodes_fn
) ();
195 insn_size
= isa
->insn_size
;
196 for (opc
= 0; opc
< new_num_opcodes
; opc
++)
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
;
207 isa
->insn_size
= insn_size
;
208 isa
->insnbuf_size
= ((isa
->insn_size
+ sizeof (xtensa_insnbuf_word
) - 1) /
209 sizeof (xtensa_insnbuf_word
));
211 qsort (isa
->opname_lookup_table
, isa
->num_opcodes
,
212 sizeof (opname_lookup_entry
), opname_lookup_compare
);
214 /* Check for duplicate opcode names. */
215 for (opc
= 1; opc
< isa
->num_opcodes
; opc
++)
217 if (!opname_lookup_compare (&isa
->opname_lookup_table
[opc
-1],
218 &isa
->opname_lookup_table
[opc
]))
220 fprintf (stderr
, "Error: Duplicate TIE opcode \"%s\"\n",
221 isa
->opname_lookup_table
[opc
].key
);
226 this_module
= isa
->num_modules
;
227 isa
->num_modules
+= 1;
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
));
235 isa
->module_opcode_base
[this_module
] = prev_num_opcodes
;
236 isa
->module_decode_fn
[this_module
] = decode_insn_fn
;
238 xtensa_default_isa
= isa
;
240 return 1; /* Library was successfully added. */
245 xtensa_load_isa (libisa_module_specifier libisa
)
247 xtensa_isa_internal
*isa
;
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
))
253 xtensa_isa_free (isa
);
256 return (xtensa_isa
) isa
;
261 xtensa_extend_isa (xtensa_isa isa
, libisa_module_specifier libisa
)
263 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*) isa
;
264 return xtensa_add_isa (intisa
, libisa
);
269 xtensa_isa_free (xtensa_isa isa
)
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
);
285 xtensa_insn_maxlength (xtensa_isa isa
)
287 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*) isa
;
288 return intisa
->insn_size
;
293 xtensa_insnbuf_size (xtensa_isa isa
)
295 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*)isa
;
296 return intisa
->insnbuf_size
;
301 xtensa_num_opcodes (xtensa_isa isa
)
303 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*) isa
;
304 return intisa
->num_opcodes
;
309 xtensa_opcode_lookup (xtensa_isa isa
, const char *opname
)
311 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*) isa
;
312 opname_lookup_entry entry
, *result
;
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
;
323 xtensa_decode_insn (xtensa_isa isa
, const xtensa_insnbuf insn
)
325 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*) isa
;
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
;
332 return XTENSA_UNDEFINED
;
336 /* Opcode information. */
339 xtensa_encode_insn (xtensa_isa isa
, xtensa_opcode opc
, xtensa_insnbuf insn
)
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
;
346 /* Convert length to 32-bit words. */
349 /* Copy the template. */
350 for (n
= 0; n
< len
; n
++)
351 insn
[n
] = template[n
];
353 /* Fill any unused buffer space with zeros. */
354 for ( ; n
< intisa
->insnbuf_size
; n
++)
360 xtensa_opcode_name (xtensa_isa isa
, xtensa_opcode opc
)
362 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*) isa
;
363 return intisa
->opcode_table
[opc
]->name
;
368 xtensa_insn_length (xtensa_isa isa
, xtensa_opcode opc
)
370 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*) isa
;
371 return intisa
->opcode_table
[opc
]->length
;
376 xtensa_insn_length_from_first_byte (xtensa_isa isa
, char first_byte
)
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);
385 xtensa_num_operands (xtensa_isa isa
, xtensa_opcode opc
)
387 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*) isa
;
388 return intisa
->opcode_table
[opc
]->iclass
->num_operands
;
393 xtensa_get_operand (xtensa_isa isa
, xtensa_opcode opc
, int opnd
)
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
)
399 return (xtensa_operand
) iclass
->operands
[opnd
];
403 /* Operand information. */
406 xtensa_operand_kind (xtensa_operand opnd
)
408 xtensa_operand_internal
*intop
= (xtensa_operand_internal
*) opnd
;
409 return intop
->operand_kind
;
414 xtensa_operand_inout (xtensa_operand opnd
)
416 xtensa_operand_internal
*intop
= (xtensa_operand_internal
*) opnd
;
422 xtensa_operand_get_field (xtensa_operand opnd
, const xtensa_insnbuf insn
)
424 xtensa_operand_internal
*intop
= (xtensa_operand_internal
*) opnd
;
425 return (*intop
->get_field
) (insn
);
430 xtensa_operand_set_field (xtensa_operand opnd
, xtensa_insnbuf insn
, uint32 val
)
432 xtensa_operand_internal
*intop
= (xtensa_operand_internal
*) opnd
;
433 return (*intop
->set_field
) (insn
, val
);
438 xtensa_operand_encode (xtensa_operand opnd
, uint32
*valp
)
440 xtensa_operand_internal
*intop
= (xtensa_operand_internal
*) opnd
;
441 return (*intop
->encode
) (valp
);
446 xtensa_operand_decode (xtensa_operand opnd
, uint32 val
)
448 xtensa_operand_internal
*intop
= (xtensa_operand_internal
*) opnd
;
449 return (*intop
->decode
) (val
);
454 xtensa_operand_isPCRelative (xtensa_operand opnd
)
456 xtensa_operand_internal
*intop
= (xtensa_operand_internal
*) opnd
;
457 return intop
->isPCRelative
;
462 xtensa_operand_do_reloc (xtensa_operand opnd
, uint32 addr
, uint32 pc
)
464 xtensa_operand_internal
*intop
= (xtensa_operand_internal
*) opnd
;
465 if (!intop
->isPCRelative
)
467 return (*intop
->do_reloc
) (addr
, pc
);
472 xtensa_operand_undo_reloc (xtensa_operand opnd
, uint32 offset
, uint32 pc
)
474 xtensa_operand_internal
*intop
= (xtensa_operand_internal
*) opnd
;
475 if (!intop
->isPCRelative
)
477 return (*intop
->undo_reloc
) (offset
, pc
);
481 /* Instruction buffers. */
484 xtensa_insnbuf_alloc (xtensa_isa isa
)
486 return (xtensa_insnbuf
) malloc (xtensa_insnbuf_size (isa
) *
487 sizeof (xtensa_insnbuf_word
));
492 xtensa_insnbuf_free (xtensa_insnbuf buf
)
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. */
503 byte_to_word_index (int byte_index
)
505 return byte_index
/ sizeof (xtensa_insnbuf_word
);
510 byte_to_bit_index (int byte_index
)
512 return (byte_index
& 0x3) * 8;
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. */
524 xtensa_insnbuf_to_chars (xtensa_isa isa
, const xtensa_insnbuf insn
, char *cp
)
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
;
531 if (intisa
->is_big_endian
)
533 start
= insn_size
- 1;
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
)
548 byte_count
= xtensa_insn_length (isa
, opc
);
549 fence_post
= start
+ (byte_count
* increment
);
551 for (i
= start
; i
!= fence_post
; i
+= increment
, ++cp
)
553 int word_inx
= byte_to_word_index (i
);
554 int bit_inx
= byte_to_bit_index (i
);
556 *cp
= (insn
[word_inx
] >> bit_inx
) & 0xff;
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. */
565 xtensa_insnbuf_from_chars (xtensa_isa isa
, xtensa_insnbuf insn
, const char* cp
)
567 xtensa_isa_internal
*intisa
= (xtensa_isa_internal
*) isa
;
568 int insn_size
= xtensa_insn_maxlength (intisa
);
569 int fence_post
, start
, increment
, i
;
571 if (intisa
->is_big_endian
)
573 start
= insn_size
- 1;
582 fence_post
= start
+ (insn_size
* increment
);
583 memset (insn
, 0, xtensa_insnbuf_size (isa
) * sizeof (xtensa_insnbuf_word
));
585 for ( i
= start
; i
!= fence_post
; i
+= increment
, ++cp
)
587 int word_inx
= byte_to_word_index (i
);
588 int bit_inx
= byte_to_bit_index (i
);
590 insn
[word_inx
] |= (*cp
& 0xff) << bit_inx
;