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