qemu/target/xtensa/xtensa-isa.c
<<
>>
Prefs
   1/* Configurable Xtensa ISA support.
   2 *
   3 * Copyright (c) 2001-2011 Tensilica Inc.
   4 *
   5 * Permission is hereby granted, free of charge, to any person obtaining
   6 * a copy of this software and associated documentation files (the
   7 * "Software"), to deal in the Software without restriction, including
   8 * without limitation the rights to use, copy, modify, merge, publish,
   9 * distribute, sublicense, and/or sell copies of the Software, and to
  10 * permit persons to whom the Software is furnished to do so, subject to
  11 * the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included
  14 * in all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23 */
  24
  25#include "qemu/osdep.h"
  26#include "xtensa-isa.h"
  27#include "xtensa-isa-internal.h"
  28
  29xtensa_isa_status xtisa_errno;
  30char xtisa_error_msg[1024];
  31
  32
  33xtensa_isa_status xtensa_isa_errno(xtensa_isa isa __attribute__ ((unused)))
  34{
  35    return xtisa_errno;
  36}
  37
  38
  39char *xtensa_isa_error_msg(xtensa_isa isa __attribute__ ((unused)))
  40{
  41    return xtisa_error_msg;
  42}
  43
  44
  45#define CHECK_ALLOC(MEM, ERRVAL) \
  46    do { \
  47        if ((MEM) == 0) { \
  48            xtisa_errno = xtensa_isa_out_of_memory; \
  49            strcpy(xtisa_error_msg, "out of memory"); \
  50            return ERRVAL; \
  51        } \
  52    } while (0)
  53
  54#define CHECK_ALLOC_FOR_INIT(MEM, ERRVAL, ERRNO_P, ERROR_MSG_P) \
  55    do { \
  56        if ((MEM) == 0) { \
  57            xtisa_errno = xtensa_isa_out_of_memory; \
  58            strcpy(xtisa_error_msg, "out of memory"); \
  59            if (ERRNO_P) { \
  60                *(ERRNO_P) = xtisa_errno; \
  61            } \
  62            if (ERROR_MSG_P) { \
  63                *(ERROR_MSG_P) = xtisa_error_msg; \
  64            } \
  65            return ERRVAL; \
  66        } \
  67    } while (0)
  68
  69
  70/* Instruction buffers. */
  71
  72int xtensa_insnbuf_size(xtensa_isa isa)
  73{
  74    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
  75    return intisa->insnbuf_size;
  76}
  77
  78
  79xtensa_insnbuf xtensa_insnbuf_alloc(xtensa_isa isa)
  80{
  81    xtensa_insnbuf result = (xtensa_insnbuf)
  82        malloc(xtensa_insnbuf_size(isa) * sizeof(xtensa_insnbuf_word));
  83
  84    CHECK_ALLOC(result, 0);
  85    return result;
  86}
  87
  88
  89void xtensa_insnbuf_free(xtensa_isa isa __attribute__ ((unused)),
  90                         xtensa_insnbuf buf)
  91{
  92    free(buf);
  93}
  94
  95
  96/*
  97 * Given <byte_index>, the index of a byte in a xtensa_insnbuf, our
  98 * internal representation of a xtensa instruction word, return the index of
  99 * its word and the bit index of its low order byte in the xtensa_insnbuf.
 100 */
 101
 102static inline int byte_to_word_index(int byte_index)
 103{
 104    return byte_index / sizeof(xtensa_insnbuf_word);
 105}
 106
 107
 108static inline int byte_to_bit_index(int byte_index)
 109{
 110    return (byte_index & 0x3) * 8;
 111}
 112
 113
 114/*
 115 * Copy an instruction in the 32-bit words pointed at by "insn" to
 116 * characters pointed at by "cp". This is more complicated than you
 117 * might think because we want 16-bit instructions in bytes 2 & 3 for
 118 * big-endian configurations. This function allows us to specify
 119 * which byte in "insn" to start with and which way to increment,
 120 * allowing trivial implementation for both big- and little-endian
 121 * configurations....and it seems to make pretty good code for
 122 * both.
 123 */
 124
 125int xtensa_insnbuf_to_chars(xtensa_isa isa,
 126                            const xtensa_insnbuf insn,
 127                            unsigned char *cp,
 128                            int num_chars)
 129{
 130    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 131    int insn_size = xtensa_isa_maxlength(isa);
 132    int fence_post, start, increment, i, byte_count;
 133    xtensa_format fmt;
 134
 135    if (num_chars == 0) {
 136        num_chars = insn_size;
 137    }
 138
 139    if (intisa->is_big_endian) {
 140        start = insn_size - 1;
 141        increment = -1;
 142    } else {
 143        start = 0;
 144        increment = 1;
 145    }
 146
 147    /*
 148     * Find the instruction format. Do nothing if the buffer does not contain
 149     * a valid instruction since we need to know how many bytes to copy.
 150     */
 151    fmt = xtensa_format_decode(isa, insn);
 152    if (fmt == XTENSA_UNDEFINED) {
 153        return XTENSA_UNDEFINED;
 154    }
 155
 156    byte_count = xtensa_format_length(isa, fmt);
 157    if (byte_count == XTENSA_UNDEFINED) {
 158        return XTENSA_UNDEFINED;
 159    }
 160
 161    if (byte_count > num_chars) {
 162        xtisa_errno = xtensa_isa_buffer_overflow;
 163        strcpy(xtisa_error_msg, "output buffer too small for instruction");
 164        return XTENSA_UNDEFINED;
 165    }
 166
 167    fence_post = start + (byte_count * increment);
 168
 169    for (i = start; i != fence_post; i += increment, ++cp) {
 170        int word_inx = byte_to_word_index(i);
 171        int bit_inx = byte_to_bit_index(i);
 172
 173        *cp = (insn[word_inx] >> bit_inx) & 0xff;
 174    }
 175
 176    return byte_count;
 177}
 178
 179
 180/*
 181 * Inward conversion from byte stream to xtensa_insnbuf. See
 182 * xtensa_insnbuf_to_chars for a discussion of why this is complicated
 183 * by endianness.
 184 */
 185
 186void xtensa_insnbuf_from_chars(xtensa_isa isa,
 187                               xtensa_insnbuf insn,
 188                               const unsigned char *cp,
 189                               int num_chars)
 190{
 191    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 192    int max_size, insn_size, fence_post, start, increment, i;
 193
 194    max_size = xtensa_isa_maxlength(isa);
 195
 196    /* Decode the instruction length so we know how many bytes to read. */
 197    insn_size = (intisa->length_decode_fn)(cp);
 198    if (insn_size == XTENSA_UNDEFINED) {
 199        /*
 200         * This should never happen when the byte stream contains a
 201         * valid instruction. Just read the maximum number of bytes....
 202         */
 203        insn_size = max_size;
 204    }
 205
 206    if (num_chars == 0 || num_chars > insn_size) {
 207        num_chars = insn_size;
 208    }
 209
 210    if (intisa->is_big_endian) {
 211        start = max_size - 1;
 212        increment = -1;
 213    } else {
 214        start = 0;
 215        increment = 1;
 216    }
 217
 218    fence_post = start + (num_chars * increment);
 219    memset(insn, 0, xtensa_insnbuf_size(isa) * sizeof(xtensa_insnbuf_word));
 220
 221    for (i = start; i != fence_post; i += increment, ++cp) {
 222        int word_inx = byte_to_word_index(i);
 223        int bit_inx = byte_to_bit_index(i);
 224
 225        insn[word_inx] |= (*cp & 0xff) << bit_inx;
 226    }
 227}
 228
 229
 230/* ISA information. */
 231
 232xtensa_isa xtensa_isa_init(void *xtensa_modules, xtensa_isa_status *errno_p,
 233                           char **error_msg_p)
 234{
 235    xtensa_isa_internal *isa = xtensa_modules;
 236    int n, is_user;
 237
 238    /* Set up the opcode name lookup table. */
 239    isa->opname_lookup_table =
 240        malloc(isa->num_opcodes * sizeof(xtensa_lookup_entry));
 241    CHECK_ALLOC_FOR_INIT(isa->opname_lookup_table, NULL, errno_p, error_msg_p);
 242    for (n = 0; n < isa->num_opcodes; n++) {
 243        isa->opname_lookup_table[n].key = isa->opcodes[n].name;
 244        isa->opname_lookup_table[n].u.opcode = n;
 245    }
 246    qsort(isa->opname_lookup_table, isa->num_opcodes,
 247          sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
 248
 249    /* Set up the state name lookup table. */
 250    isa->state_lookup_table =
 251        malloc(isa->num_states * sizeof(xtensa_lookup_entry));
 252    CHECK_ALLOC_FOR_INIT(isa->state_lookup_table, NULL, errno_p, error_msg_p);
 253    for (n = 0; n < isa->num_states; n++) {
 254        isa->state_lookup_table[n].key = isa->states[n].name;
 255        isa->state_lookup_table[n].u.state = n;
 256    }
 257    qsort(isa->state_lookup_table, isa->num_states,
 258          sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
 259
 260    /* Set up the sysreg name lookup table. */
 261    isa->sysreg_lookup_table =
 262        malloc(isa->num_sysregs * sizeof(xtensa_lookup_entry));
 263    CHECK_ALLOC_FOR_INIT(isa->sysreg_lookup_table, NULL, errno_p, error_msg_p);
 264    for (n = 0; n < isa->num_sysregs; n++) {
 265        isa->sysreg_lookup_table[n].key = isa->sysregs[n].name;
 266        isa->sysreg_lookup_table[n].u.sysreg = n;
 267    }
 268    qsort(isa->sysreg_lookup_table, isa->num_sysregs,
 269          sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
 270
 271    /* Set up the user & system sysreg number tables. */
 272    for (is_user = 0; is_user < 2; is_user++) {
 273        isa->sysreg_table[is_user] =
 274            malloc((isa->max_sysreg_num[is_user] + 1) * sizeof(xtensa_sysreg));
 275        CHECK_ALLOC_FOR_INIT(isa->sysreg_table[is_user], NULL,
 276                             errno_p, error_msg_p);
 277
 278        for (n = 0; n <= isa->max_sysreg_num[is_user]; n++) {
 279            isa->sysreg_table[is_user][n] = XTENSA_UNDEFINED;
 280        }
 281    }
 282    for (n = 0; n < isa->num_sysregs; n++) {
 283        xtensa_sysreg_internal *sreg = &isa->sysregs[n];
 284        is_user = sreg->is_user;
 285
 286        if (sreg->number >= 0) {
 287            isa->sysreg_table[is_user][sreg->number] = n;
 288        }
 289    }
 290
 291    /* Set up the interface lookup table. */
 292    isa->interface_lookup_table =
 293        malloc(isa->num_interfaces * sizeof(xtensa_lookup_entry));
 294    CHECK_ALLOC_FOR_INIT(isa->interface_lookup_table, NULL, errno_p,
 295                         error_msg_p);
 296    for (n = 0; n < isa->num_interfaces; n++) {
 297        isa->interface_lookup_table[n].key = isa->interfaces[n].name;
 298        isa->interface_lookup_table[n].u.intf = n;
 299    }
 300    qsort(isa->interface_lookup_table, isa->num_interfaces,
 301          sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
 302
 303    /* Set up the funcUnit lookup table. */
 304    isa->funcUnit_lookup_table =
 305        malloc(isa->num_funcUnits * sizeof(xtensa_lookup_entry));
 306    CHECK_ALLOC_FOR_INIT(isa->funcUnit_lookup_table, NULL, errno_p,
 307                         error_msg_p);
 308    for (n = 0; n < isa->num_funcUnits; n++) {
 309        isa->funcUnit_lookup_table[n].key = isa->funcUnits[n].name;
 310        isa->funcUnit_lookup_table[n].u.fun = n;
 311    }
 312    qsort(isa->funcUnit_lookup_table, isa->num_funcUnits,
 313          sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
 314
 315    isa->insnbuf_size = ((isa->insn_size + sizeof(xtensa_insnbuf_word) - 1) /
 316                         sizeof(xtensa_insnbuf_word));
 317    isa->num_stages = XTENSA_UNDEFINED;
 318
 319    return (xtensa_isa)isa;
 320}
 321
 322
 323void xtensa_isa_free(xtensa_isa isa)
 324{
 325    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 326    int n;
 327
 328    /*
 329     * With this version of the code, the xtensa_isa structure is not
 330     * dynamically allocated, so this function is not essential. Free
 331     * the memory allocated by xtensa_isa_init and restore the xtensa_isa
 332     * structure to its initial state.
 333     */
 334
 335    if (intisa->opname_lookup_table) {
 336        free(intisa->opname_lookup_table);
 337        intisa->opname_lookup_table = 0;
 338    }
 339
 340    if (intisa->state_lookup_table) {
 341        free(intisa->state_lookup_table);
 342        intisa->state_lookup_table = 0;
 343    }
 344
 345    if (intisa->sysreg_lookup_table) {
 346        free(intisa->sysreg_lookup_table);
 347        intisa->sysreg_lookup_table = 0;
 348    }
 349    for (n = 0; n < 2; n++) {
 350        if (intisa->sysreg_table[n]) {
 351            free(intisa->sysreg_table[n]);
 352            intisa->sysreg_table[n] = 0;
 353        }
 354    }
 355
 356    if (intisa->interface_lookup_table) {
 357        free(intisa->interface_lookup_table);
 358        intisa->interface_lookup_table = 0;
 359    }
 360
 361    if (intisa->funcUnit_lookup_table) {
 362        free(intisa->funcUnit_lookup_table);
 363        intisa->funcUnit_lookup_table = 0;
 364    }
 365}
 366
 367
 368int xtensa_isa_name_compare(const void *v1, const void *v2)
 369{
 370    xtensa_lookup_entry *e1 = (xtensa_lookup_entry *)v1;
 371    xtensa_lookup_entry *e2 = (xtensa_lookup_entry *)v2;
 372
 373    return strcasecmp(e1->key, e2->key);
 374}
 375
 376
 377int xtensa_isa_maxlength(xtensa_isa isa)
 378{
 379    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 380    return intisa->insn_size;
 381}
 382
 383
 384int xtensa_isa_length_from_chars(xtensa_isa isa, const unsigned char *cp)
 385{
 386    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 387    return (intisa->length_decode_fn)(cp);
 388}
 389
 390
 391int xtensa_isa_num_pipe_stages(xtensa_isa isa)
 392{
 393    xtensa_opcode opcode;
 394    xtensa_funcUnit_use *use;
 395    int num_opcodes, num_uses;
 396    int i, stage, max_stage;
 397    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 398
 399    /* Only compute the value once. */
 400    if (intisa->num_stages != XTENSA_UNDEFINED) {
 401        return intisa->num_stages;
 402    }
 403
 404    max_stage = -1;
 405
 406    num_opcodes = xtensa_isa_num_opcodes(isa);
 407    for (opcode = 0; opcode < num_opcodes; opcode++) {
 408        num_uses = xtensa_opcode_num_funcUnit_uses(isa, opcode);
 409        for (i = 0; i < num_uses; i++) {
 410            use = xtensa_opcode_funcUnit_use(isa, opcode, i);
 411            stage = use->stage;
 412            if (stage > max_stage) {
 413                max_stage = stage;
 414            }
 415        }
 416    }
 417
 418    intisa->num_stages = max_stage + 1;
 419    return intisa->num_states;
 420}
 421
 422
 423int xtensa_isa_num_formats(xtensa_isa isa)
 424{
 425    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 426    return intisa->num_formats;
 427}
 428
 429
 430int xtensa_isa_num_opcodes(xtensa_isa isa)
 431{
 432    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 433    return intisa->num_opcodes;
 434}
 435
 436
 437int xtensa_isa_num_regfiles(xtensa_isa isa)
 438{
 439    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 440    return intisa->num_regfiles;
 441}
 442
 443
 444int xtensa_isa_num_states(xtensa_isa isa)
 445{
 446    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 447    return intisa->num_states;
 448}
 449
 450
 451int xtensa_isa_num_sysregs(xtensa_isa isa)
 452{
 453    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 454    return intisa->num_sysregs;
 455}
 456
 457
 458int xtensa_isa_num_interfaces(xtensa_isa isa)
 459{
 460    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 461    return intisa->num_interfaces;
 462}
 463
 464
 465int xtensa_isa_num_funcUnits(xtensa_isa isa)
 466{
 467    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 468    return intisa->num_funcUnits;
 469}
 470
 471
 472/* Instruction formats. */
 473
 474
 475#define CHECK_FORMAT(INTISA, FMT, ERRVAL) \
 476    do { \
 477        if ((FMT) < 0 || (FMT) >= (INTISA)->num_formats) { \
 478            xtisa_errno = xtensa_isa_bad_format; \
 479            strcpy(xtisa_error_msg, "invalid format specifier"); \
 480            return ERRVAL; \
 481        } \
 482    } while (0)
 483
 484
 485#define CHECK_SLOT(INTISA, FMT, SLOT, ERRVAL) \
 486    do { \
 487        if ((SLOT) < 0 || (SLOT) >= (INTISA)->formats[FMT].num_slots) { \
 488            xtisa_errno = xtensa_isa_bad_slot; \
 489            strcpy(xtisa_error_msg, "invalid slot specifier"); \
 490            return ERRVAL; \
 491        } \
 492    } while (0)
 493
 494
 495const char *xtensa_format_name(xtensa_isa isa, xtensa_format fmt)
 496{
 497    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 498
 499    CHECK_FORMAT(intisa, fmt, NULL);
 500    return intisa->formats[fmt].name;
 501}
 502
 503
 504xtensa_format xtensa_format_lookup(xtensa_isa isa, const char *fmtname)
 505{
 506    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 507    int fmt;
 508
 509    if (!fmtname || !*fmtname) {
 510        xtisa_errno = xtensa_isa_bad_format;
 511        strcpy(xtisa_error_msg, "invalid format name");
 512        return XTENSA_UNDEFINED;
 513    }
 514
 515    for (fmt = 0; fmt < intisa->num_formats; fmt++) {
 516        if (strcasecmp(fmtname, intisa->formats[fmt].name) == 0) {
 517            return fmt;
 518        }
 519    }
 520
 521    xtisa_errno = xtensa_isa_bad_format;
 522    sprintf(xtisa_error_msg, "format \"%s\" not recognized", fmtname);
 523    return XTENSA_UNDEFINED;
 524}
 525
 526
 527xtensa_format xtensa_format_decode(xtensa_isa isa, const xtensa_insnbuf insn)
 528{
 529    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 530    xtensa_format fmt;
 531
 532    fmt = (intisa->format_decode_fn)(insn);
 533    if (fmt != XTENSA_UNDEFINED) {
 534        return fmt;
 535    }
 536
 537    xtisa_errno = xtensa_isa_bad_format;
 538    strcpy(xtisa_error_msg, "cannot decode instruction format");
 539    return XTENSA_UNDEFINED;
 540}
 541
 542
 543int xtensa_format_encode(xtensa_isa isa, xtensa_format fmt,
 544                         xtensa_insnbuf insn)
 545{
 546    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 547
 548    CHECK_FORMAT(intisa, fmt, -1);
 549    (*intisa->formats[fmt].encode_fn)(insn);
 550    return 0;
 551}
 552
 553
 554int xtensa_format_length(xtensa_isa isa, xtensa_format fmt)
 555{
 556    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 557
 558    CHECK_FORMAT(intisa, fmt, XTENSA_UNDEFINED);
 559    return intisa->formats[fmt].length;
 560}
 561
 562
 563int xtensa_format_num_slots(xtensa_isa isa, xtensa_format fmt)
 564{
 565    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 566
 567    CHECK_FORMAT(intisa, fmt, XTENSA_UNDEFINED);
 568    return intisa->formats[fmt].num_slots;
 569}
 570
 571
 572xtensa_opcode xtensa_format_slot_nop_opcode(xtensa_isa isa, xtensa_format fmt,
 573                                            int slot)
 574{
 575    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 576    int slot_id;
 577
 578    CHECK_FORMAT(intisa, fmt, XTENSA_UNDEFINED);
 579    CHECK_SLOT(intisa, fmt, slot, XTENSA_UNDEFINED);
 580
 581    slot_id = intisa->formats[fmt].slot_id[slot];
 582    return xtensa_opcode_lookup(isa, intisa->slots[slot_id].nop_name);
 583}
 584
 585
 586int xtensa_format_get_slot(xtensa_isa isa, xtensa_format fmt, int slot,
 587                           const xtensa_insnbuf insn, xtensa_insnbuf slotbuf)
 588{
 589    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 590    int slot_id;
 591
 592    CHECK_FORMAT(intisa, fmt, -1);
 593    CHECK_SLOT(intisa, fmt, slot, -1);
 594
 595    slot_id = intisa->formats[fmt].slot_id[slot];
 596    (*intisa->slots[slot_id].get_fn)(insn, slotbuf);
 597    return 0;
 598}
 599
 600
 601int xtensa_format_set_slot(xtensa_isa isa, xtensa_format fmt, int slot,
 602                           xtensa_insnbuf insn, const xtensa_insnbuf slotbuf)
 603{
 604    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 605    int slot_id;
 606
 607    CHECK_FORMAT(intisa, fmt, -1);
 608    CHECK_SLOT(intisa, fmt, slot, -1);
 609
 610    slot_id = intisa->formats[fmt].slot_id[slot];
 611    (*intisa->slots[slot_id].set_fn)(insn, slotbuf);
 612    return 0;
 613}
 614
 615
 616/* Opcode information. */
 617
 618
 619#define CHECK_OPCODE(INTISA, OPC, ERRVAL) \
 620    do { \
 621        if ((OPC) < 0 || (OPC) >= (INTISA)->num_opcodes) { \
 622            xtisa_errno = xtensa_isa_bad_opcode; \
 623            strcpy(xtisa_error_msg, "invalid opcode specifier"); \
 624            return ERRVAL; \
 625        } \
 626    } while (0)
 627
 628
 629xtensa_opcode xtensa_opcode_lookup(xtensa_isa isa, const char *opname)
 630{
 631    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 632    xtensa_lookup_entry entry, *result = 0;
 633
 634    if (!opname || !*opname) {
 635        xtisa_errno = xtensa_isa_bad_opcode;
 636        strcpy(xtisa_error_msg, "invalid opcode name");
 637        return XTENSA_UNDEFINED;
 638    }
 639
 640    if (intisa->num_opcodes != 0) {
 641        entry.key = opname;
 642        result = bsearch(&entry, intisa->opname_lookup_table,
 643                         intisa->num_opcodes, sizeof(xtensa_lookup_entry),
 644                         xtensa_isa_name_compare);
 645    }
 646
 647    if (!result) {
 648        xtisa_errno = xtensa_isa_bad_opcode;
 649        sprintf(xtisa_error_msg, "opcode \"%s\" not recognized", opname);
 650        return XTENSA_UNDEFINED;
 651    }
 652
 653    return result->u.opcode;
 654}
 655
 656
 657xtensa_opcode xtensa_opcode_decode(xtensa_isa isa, xtensa_format fmt, int slot,
 658                                   const xtensa_insnbuf slotbuf)
 659{
 660    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 661    int slot_id;
 662    xtensa_opcode opc;
 663
 664    CHECK_FORMAT(intisa, fmt, XTENSA_UNDEFINED);
 665    CHECK_SLOT(intisa, fmt, slot, XTENSA_UNDEFINED);
 666
 667    slot_id = intisa->formats[fmt].slot_id[slot];
 668
 669    opc = (intisa->slots[slot_id].opcode_decode_fn) (slotbuf);
 670    if (opc != XTENSA_UNDEFINED) {
 671        return opc;
 672    }
 673
 674    xtisa_errno = xtensa_isa_bad_opcode;
 675    strcpy(xtisa_error_msg, "cannot decode opcode");
 676    return XTENSA_UNDEFINED;
 677}
 678
 679
 680int xtensa_opcode_encode(xtensa_isa isa, xtensa_format fmt, int slot,
 681                         xtensa_insnbuf slotbuf, xtensa_opcode opc)
 682{
 683    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 684    int slot_id;
 685    xtensa_opcode_encode_fn encode_fn;
 686
 687    CHECK_FORMAT(intisa, fmt, -1);
 688    CHECK_SLOT(intisa, fmt, slot, -1);
 689    CHECK_OPCODE(intisa, opc, -1);
 690
 691    slot_id = intisa->formats[fmt].slot_id[slot];
 692    encode_fn = intisa->opcodes[opc].encode_fns[slot_id];
 693    if (!encode_fn) {
 694        xtisa_errno = xtensa_isa_wrong_slot;
 695        sprintf(xtisa_error_msg,
 696                "opcode \"%s\" is not allowed in slot %d of format \"%s\"",
 697                intisa->opcodes[opc].name, slot, intisa->formats[fmt].name);
 698        return -1;
 699    }
 700    (*encode_fn)(slotbuf);
 701    return 0;
 702}
 703
 704
 705const char *xtensa_opcode_name(xtensa_isa isa, xtensa_opcode opc)
 706{
 707    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 708
 709    CHECK_OPCODE(intisa, opc, NULL);
 710    return intisa->opcodes[opc].name;
 711}
 712
 713
 714int xtensa_opcode_is_branch(xtensa_isa isa, xtensa_opcode opc)
 715{
 716    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 717
 718    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
 719    if ((intisa->opcodes[opc].flags & XTENSA_OPCODE_IS_BRANCH) != 0) {
 720        return 1;
 721    }
 722    return 0;
 723}
 724
 725
 726int xtensa_opcode_is_jump(xtensa_isa isa, xtensa_opcode opc)
 727{
 728    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 729
 730    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
 731    if ((intisa->opcodes[opc].flags & XTENSA_OPCODE_IS_JUMP) != 0) {
 732        return 1;
 733    }
 734    return 0;
 735}
 736
 737
 738int xtensa_opcode_is_loop(xtensa_isa isa, xtensa_opcode opc)
 739{
 740    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 741
 742    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
 743    if ((intisa->opcodes[opc].flags & XTENSA_OPCODE_IS_LOOP) != 0) {
 744        return 1;
 745    }
 746    return 0;
 747}
 748
 749
 750int xtensa_opcode_is_call(xtensa_isa isa, xtensa_opcode opc)
 751{
 752    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 753
 754    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
 755    if ((intisa->opcodes[opc].flags & XTENSA_OPCODE_IS_CALL) != 0) {
 756        return 1;
 757    }
 758    return 0;
 759}
 760
 761
 762int xtensa_opcode_num_operands(xtensa_isa isa, xtensa_opcode opc)
 763{
 764    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 765    int iclass_id;
 766
 767    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
 768    iclass_id = intisa->opcodes[opc].iclass_id;
 769    return intisa->iclasses[iclass_id].num_operands;
 770}
 771
 772
 773int xtensa_opcode_num_stateOperands(xtensa_isa isa, xtensa_opcode opc)
 774{
 775    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 776    int iclass_id;
 777
 778    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
 779    iclass_id = intisa->opcodes[opc].iclass_id;
 780    return intisa->iclasses[iclass_id].num_stateOperands;
 781}
 782
 783
 784int xtensa_opcode_num_interfaceOperands(xtensa_isa isa, xtensa_opcode opc)
 785{
 786    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 787    int iclass_id;
 788
 789    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
 790    iclass_id = intisa->opcodes[opc].iclass_id;
 791    return intisa->iclasses[iclass_id].num_interfaceOperands;
 792}
 793
 794
 795int xtensa_opcode_num_funcUnit_uses(xtensa_isa isa, xtensa_opcode opc)
 796{
 797    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 798
 799    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
 800    return intisa->opcodes[opc].num_funcUnit_uses;
 801}
 802
 803
 804xtensa_funcUnit_use *xtensa_opcode_funcUnit_use(xtensa_isa isa,
 805                                                xtensa_opcode opc, int u)
 806{
 807    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 808
 809    CHECK_OPCODE(intisa, opc, NULL);
 810    if (u < 0 || u >= intisa->opcodes[opc].num_funcUnit_uses) {
 811        xtisa_errno = xtensa_isa_bad_funcUnit;
 812        sprintf(xtisa_error_msg, "invalid functional unit use number (%d); "
 813                "opcode \"%s\" has %d", u, intisa->opcodes[opc].name,
 814                intisa->opcodes[opc].num_funcUnit_uses);
 815        return NULL;
 816    }
 817    return &intisa->opcodes[opc].funcUnit_uses[u];
 818}
 819
 820
 821/* Operand information. */
 822
 823
 824#define CHECK_OPERAND(INTISA, OPC, ICLASS, OPND, ERRVAL) \
 825    do { \
 826        if ((OPND) < 0 || (OPND) >= (ICLASS)->num_operands) { \
 827            xtisa_errno = xtensa_isa_bad_operand; \
 828            sprintf(xtisa_error_msg, "invalid operand number (%d); " \
 829                    "opcode \"%s\" has %d operands", (OPND), \
 830                    (INTISA)->opcodes[(OPC)].name, (ICLASS)->num_operands); \
 831            return ERRVAL; \
 832        } \
 833    } while (0)
 834
 835
 836static xtensa_operand_internal *get_operand(xtensa_isa_internal *intisa,
 837                                            xtensa_opcode opc, int opnd)
 838{
 839    xtensa_iclass_internal *iclass;
 840    int iclass_id, operand_id;
 841
 842    CHECK_OPCODE(intisa, opc, NULL);
 843    iclass_id = intisa->opcodes[opc].iclass_id;
 844    iclass = &intisa->iclasses[iclass_id];
 845    CHECK_OPERAND(intisa, opc, iclass, opnd, NULL);
 846    operand_id = iclass->operands[opnd].u.operand_id;
 847    return &intisa->operands[operand_id];
 848}
 849
 850
 851const char *xtensa_operand_name(xtensa_isa isa, xtensa_opcode opc, int opnd)
 852{
 853    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 854    xtensa_operand_internal *intop;
 855
 856    intop = get_operand(intisa, opc, opnd);
 857    if (!intop) {
 858        return NULL;
 859    }
 860    return intop->name;
 861}
 862
 863
 864int xtensa_operand_is_visible(xtensa_isa isa, xtensa_opcode opc, int opnd)
 865{
 866    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 867    xtensa_iclass_internal *iclass;
 868    int iclass_id, operand_id;
 869    xtensa_operand_internal *intop;
 870
 871    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
 872    iclass_id = intisa->opcodes[opc].iclass_id;
 873    iclass = &intisa->iclasses[iclass_id];
 874    CHECK_OPERAND(intisa, opc, iclass, opnd, XTENSA_UNDEFINED);
 875
 876    /* Special case for "sout" operands. */
 877    if (iclass->operands[opnd].inout == 's') {
 878        return 0;
 879    }
 880
 881    operand_id = iclass->operands[opnd].u.operand_id;
 882    intop = &intisa->operands[operand_id];
 883
 884    if ((intop->flags & XTENSA_OPERAND_IS_INVISIBLE) == 0) {
 885        return 1;
 886    }
 887    return 0;
 888}
 889
 890
 891char xtensa_operand_inout(xtensa_isa isa, xtensa_opcode opc, int opnd)
 892{
 893    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 894    xtensa_iclass_internal *iclass;
 895    int iclass_id;
 896    char inout;
 897
 898    CHECK_OPCODE(intisa, opc, 0);
 899    iclass_id = intisa->opcodes[opc].iclass_id;
 900    iclass = &intisa->iclasses[iclass_id];
 901    CHECK_OPERAND(intisa, opc, iclass, opnd, 0);
 902    inout = iclass->operands[opnd].inout;
 903
 904    /* Special case for "sout" and "_sin" operands. */
 905    if (inout == 's') {
 906        return 'o';
 907    }
 908    if (inout == 't') {
 909        return 'i';
 910    }
 911    return inout;
 912}
 913
 914
 915int xtensa_operand_get_field(xtensa_isa isa, xtensa_opcode opc, int opnd,
 916                             xtensa_format fmt, int slot,
 917                             const xtensa_insnbuf slotbuf, uint32_t *valp)
 918{
 919    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 920    xtensa_operand_internal *intop;
 921    int slot_id;
 922    xtensa_get_field_fn get_fn;
 923
 924    intop = get_operand(intisa, opc, opnd);
 925    if (!intop) {
 926        return -1;
 927    }
 928
 929    CHECK_FORMAT(intisa, fmt, -1);
 930    CHECK_SLOT(intisa, fmt, slot, -1);
 931
 932    slot_id = intisa->formats[fmt].slot_id[slot];
 933    if (intop->field_id == XTENSA_UNDEFINED) {
 934        xtisa_errno = xtensa_isa_no_field;
 935        strcpy(xtisa_error_msg, "implicit operand has no field");
 936        return -1;
 937    }
 938    get_fn = intisa->slots[slot_id].get_field_fns[intop->field_id];
 939    if (!get_fn) {
 940        xtisa_errno = xtensa_isa_wrong_slot;
 941        sprintf(xtisa_error_msg,
 942                "operand \"%s\" does not exist in slot %d of format \"%s\"",
 943                intop->name, slot, intisa->formats[fmt].name);
 944        return -1;
 945    }
 946    *valp = (*get_fn)(slotbuf);
 947    return 0;
 948}
 949
 950
 951int xtensa_operand_set_field(xtensa_isa isa, xtensa_opcode opc, int opnd,
 952                             xtensa_format fmt, int slot,
 953                             xtensa_insnbuf slotbuf, uint32_t val)
 954{
 955    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 956    xtensa_operand_internal *intop;
 957    int slot_id;
 958    xtensa_set_field_fn set_fn;
 959
 960    intop = get_operand(intisa, opc, opnd);
 961    if (!intop) {
 962        return -1;
 963    }
 964
 965    CHECK_FORMAT(intisa, fmt, -1);
 966    CHECK_SLOT(intisa, fmt, slot, -1);
 967
 968    slot_id = intisa->formats[fmt].slot_id[slot];
 969    if (intop->field_id == XTENSA_UNDEFINED) {
 970        xtisa_errno = xtensa_isa_no_field;
 971        strcpy(xtisa_error_msg, "implicit operand has no field");
 972        return -1;
 973    }
 974    set_fn = intisa->slots[slot_id].set_field_fns[intop->field_id];
 975    if (!set_fn) {
 976        xtisa_errno = xtensa_isa_wrong_slot;
 977        sprintf(xtisa_error_msg,
 978                "operand \"%s\" does not exist in slot %d of format \"%s\"",
 979                intop->name, slot, intisa->formats[fmt].name);
 980        return -1;
 981    }
 982    (*set_fn)(slotbuf, val);
 983    return 0;
 984}
 985
 986
 987int xtensa_operand_encode(xtensa_isa isa, xtensa_opcode opc, int opnd,
 988                          uint32_t *valp)
 989{
 990    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
 991    xtensa_operand_internal *intop;
 992    uint32_t test_val, orig_val;
 993
 994    intop = get_operand(intisa, opc, opnd);
 995    if (!intop) {
 996        return -1;
 997    }
 998
 999    if (!intop->encode) {
1000        /*
1001         * This is a default operand for a field. How can we tell if the
1002         * value fits in the field?  Write the value into the field,
1003         * read it back, and then make sure we get the same value.
1004         */
1005        static xtensa_insnbuf tmpbuf;
1006        int slot_id;
1007
1008        if (!tmpbuf) {
1009            tmpbuf = xtensa_insnbuf_alloc(isa);
1010            CHECK_ALLOC(tmpbuf, -1);
1011        }
1012
1013        /*
1014         * A default operand is always associated with a field,
1015         * but check just to be sure....
1016         */
1017        if (intop->field_id == XTENSA_UNDEFINED) {
1018            xtisa_errno = xtensa_isa_internal_error;
1019            strcpy(xtisa_error_msg, "operand has no field");
1020            return -1;
1021        }
1022
1023        /* Find some slot that includes the field. */
1024        for (slot_id = 0; slot_id < intisa->num_slots; slot_id++) {
1025            xtensa_get_field_fn get_fn =
1026                intisa->slots[slot_id].get_field_fns[intop->field_id];
1027            xtensa_set_field_fn set_fn =
1028                intisa->slots[slot_id].set_field_fns[intop->field_id];
1029
1030            if (get_fn && set_fn) {
1031                (*set_fn)(tmpbuf, *valp);
1032                return (*get_fn)(tmpbuf) != *valp;
1033            }
1034        }
1035
1036        /* Couldn't find any slot containing the field.... */
1037        xtisa_errno = xtensa_isa_no_field;
1038        strcpy(xtisa_error_msg, "field does not exist in any slot");
1039        return -1;
1040    }
1041
1042    /*
1043     * Encode the value. In some cases, the encoding function may detect
1044     * errors, but most of the time the only way to determine if the value
1045     * was successfully encoded is to decode it and check if it matches
1046     * the original value.
1047     */
1048    orig_val = *valp;
1049    if ((*intop->encode)(valp) ||
1050        (test_val = *valp, (*intop->decode)(&test_val)) ||
1051        test_val != orig_val) {
1052        xtisa_errno = xtensa_isa_bad_value;
1053        sprintf(xtisa_error_msg, "cannot encode operand value 0x%08x", *valp);
1054        return -1;
1055    }
1056
1057    return 0;
1058}
1059
1060
1061int xtensa_operand_decode(xtensa_isa isa, xtensa_opcode opc, int opnd,
1062                          uint32_t *valp)
1063{
1064    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1065    xtensa_operand_internal *intop;
1066
1067    intop = get_operand(intisa, opc, opnd);
1068    if (!intop) {
1069        return -1;
1070    }
1071
1072    /* Use identity function for "default" operands. */
1073    if (!intop->decode) {
1074        return 0;
1075    }
1076
1077    if ((*intop->decode)(valp)) {
1078        xtisa_errno = xtensa_isa_bad_value;
1079        sprintf(xtisa_error_msg, "cannot decode operand value 0x%08x", *valp);
1080        return -1;
1081    }
1082    return 0;
1083}
1084
1085
1086int xtensa_operand_is_register(xtensa_isa isa, xtensa_opcode opc, int opnd)
1087{
1088    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1089    xtensa_operand_internal *intop;
1090
1091    intop = get_operand(intisa, opc, opnd);
1092    if (!intop) {
1093        return XTENSA_UNDEFINED;
1094    }
1095
1096    if ((intop->flags & XTENSA_OPERAND_IS_REGISTER) != 0) {
1097        return 1;
1098    }
1099    return 0;
1100}
1101
1102
1103xtensa_regfile xtensa_operand_regfile(xtensa_isa isa, xtensa_opcode opc,
1104                                      int opnd)
1105{
1106    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1107    xtensa_operand_internal *intop;
1108
1109    intop = get_operand(intisa, opc, opnd);
1110    if (!intop) {
1111        return XTENSA_UNDEFINED;
1112    }
1113
1114    return intop->regfile;
1115}
1116
1117
1118int xtensa_operand_num_regs(xtensa_isa isa, xtensa_opcode opc, int opnd)
1119{
1120    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1121    xtensa_operand_internal *intop;
1122
1123    intop = get_operand(intisa, opc, opnd);
1124    if (!intop) {
1125        return XTENSA_UNDEFINED;
1126    }
1127
1128    return intop->num_regs;
1129}
1130
1131
1132int xtensa_operand_is_known_reg(xtensa_isa isa, xtensa_opcode opc, int opnd)
1133{
1134    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1135    xtensa_operand_internal *intop;
1136
1137    intop = get_operand(intisa, opc, opnd);
1138    if (!intop) {
1139        return XTENSA_UNDEFINED;
1140    }
1141
1142    if ((intop->flags & XTENSA_OPERAND_IS_UNKNOWN) == 0) {
1143        return 1;
1144    }
1145    return 0;
1146}
1147
1148
1149int xtensa_operand_is_PCrelative(xtensa_isa isa, xtensa_opcode opc, int opnd)
1150{
1151    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1152    xtensa_operand_internal *intop;
1153
1154    intop = get_operand(intisa, opc, opnd);
1155    if (!intop) {
1156        return XTENSA_UNDEFINED;
1157    }
1158
1159    if ((intop->flags & XTENSA_OPERAND_IS_PCRELATIVE) != 0) {
1160        return 1;
1161    }
1162    return 0;
1163}
1164
1165
1166int xtensa_operand_do_reloc(xtensa_isa isa, xtensa_opcode opc, int opnd,
1167                            uint32_t *valp, uint32_t pc)
1168{
1169    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1170    xtensa_operand_internal *intop;
1171
1172    intop = get_operand(intisa, opc, opnd);
1173    if (!intop) {
1174        return -1;
1175    }
1176
1177    if ((intop->flags & XTENSA_OPERAND_IS_PCRELATIVE) == 0) {
1178        return 0;
1179    }
1180
1181    if (!intop->do_reloc) {
1182        xtisa_errno = xtensa_isa_internal_error;
1183        strcpy(xtisa_error_msg, "operand missing do_reloc function");
1184        return -1;
1185    }
1186
1187    if ((*intop->do_reloc)(valp, pc)) {
1188        xtisa_errno = xtensa_isa_bad_value;
1189        sprintf(xtisa_error_msg,
1190                "do_reloc failed for value 0x%08x at PC 0x%08x", *valp, pc);
1191        return -1;
1192    }
1193
1194    return 0;
1195}
1196
1197
1198int xtensa_operand_undo_reloc(xtensa_isa isa, xtensa_opcode opc, int opnd,
1199                              uint32_t *valp, uint32_t pc)
1200{
1201    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1202    xtensa_operand_internal *intop;
1203
1204    intop = get_operand(intisa, opc, opnd);
1205    if (!intop) {
1206        return -1;
1207    }
1208
1209    if ((intop->flags & XTENSA_OPERAND_IS_PCRELATIVE) == 0) {
1210        return 0;
1211    }
1212
1213    if (!intop->undo_reloc) {
1214        xtisa_errno = xtensa_isa_internal_error;
1215        strcpy(xtisa_error_msg, "operand missing undo_reloc function");
1216        return -1;
1217    }
1218
1219    if ((*intop->undo_reloc)(valp, pc)) {
1220        xtisa_errno = xtensa_isa_bad_value;
1221        sprintf(xtisa_error_msg,
1222                "undo_reloc failed for value 0x%08x at PC 0x%08x", *valp, pc);
1223        return -1;
1224    }
1225
1226    return 0;
1227}
1228
1229
1230/* State Operands. */
1231
1232
1233#define CHECK_STATE_OPERAND(INTISA, OPC, ICLASS, STOP, ERRVAL) \
1234    do { \
1235        if ((STOP) < 0 || (STOP) >= (ICLASS)->num_stateOperands) { \
1236            xtisa_errno = xtensa_isa_bad_operand; \
1237            sprintf(xtisa_error_msg, "invalid state operand number (%d); " \
1238                    "opcode \"%s\" has %d state operands", (STOP), \
1239                    (INTISA)->opcodes[(OPC)].name, \
1240                    (ICLASS)->num_stateOperands); \
1241            return ERRVAL; \
1242        } \
1243    } while (0)
1244
1245
1246xtensa_state xtensa_stateOperand_state(xtensa_isa isa, xtensa_opcode opc,
1247                                       int stOp)
1248{
1249    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1250    xtensa_iclass_internal *iclass;
1251    int iclass_id;
1252
1253    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
1254    iclass_id = intisa->opcodes[opc].iclass_id;
1255    iclass = &intisa->iclasses[iclass_id];
1256    CHECK_STATE_OPERAND(intisa, opc, iclass, stOp, XTENSA_UNDEFINED);
1257    return iclass->stateOperands[stOp].u.state;
1258}
1259
1260
1261char xtensa_stateOperand_inout(xtensa_isa isa, xtensa_opcode opc, int stOp)
1262{
1263    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1264    xtensa_iclass_internal *iclass;
1265    int iclass_id;
1266
1267    CHECK_OPCODE(intisa, opc, 0);
1268    iclass_id = intisa->opcodes[opc].iclass_id;
1269    iclass = &intisa->iclasses[iclass_id];
1270    CHECK_STATE_OPERAND(intisa, opc, iclass, stOp, 0);
1271    return iclass->stateOperands[stOp].inout;
1272}
1273
1274
1275/* Interface Operands. */
1276
1277
1278#define CHECK_INTERFACE_OPERAND(INTISA, OPC, ICLASS, IFOP, ERRVAL) \
1279    do { \
1280        if ((IFOP) < 0 || (IFOP) >= (ICLASS)->num_interfaceOperands) { \
1281            xtisa_errno = xtensa_isa_bad_operand; \
1282            sprintf(xtisa_error_msg, \
1283                    "invalid interface operand number (%d); " \
1284                    "opcode \"%s\" has %d interface operands", (IFOP), \
1285                    (INTISA)->opcodes[(OPC)].name, \
1286                    (ICLASS)->num_interfaceOperands); \
1287            return ERRVAL; \
1288        } \
1289    } while (0)
1290
1291
1292xtensa_interface xtensa_interfaceOperand_interface(xtensa_isa isa,
1293                                                   xtensa_opcode opc,
1294                                                   int ifOp)
1295{
1296    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1297    xtensa_iclass_internal *iclass;
1298    int iclass_id;
1299
1300    CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
1301    iclass_id = intisa->opcodes[opc].iclass_id;
1302    iclass = &intisa->iclasses[iclass_id];
1303    CHECK_INTERFACE_OPERAND(intisa, opc, iclass, ifOp, XTENSA_UNDEFINED);
1304    return iclass->interfaceOperands[ifOp];
1305}
1306
1307
1308/* Register Files. */
1309
1310
1311#define CHECK_REGFILE(INTISA, RF, ERRVAL) \
1312    do { \
1313        if ((RF) < 0 || (RF) >= (INTISA)->num_regfiles) { \
1314            xtisa_errno = xtensa_isa_bad_regfile; \
1315            strcpy(xtisa_error_msg, "invalid regfile specifier"); \
1316            return ERRVAL; \
1317        } \
1318    } while (0)
1319
1320
1321xtensa_regfile xtensa_regfile_lookup(xtensa_isa isa, const char *name)
1322{
1323    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1324    int n;
1325
1326    if (!name || !*name) {
1327        xtisa_errno = xtensa_isa_bad_regfile;
1328        strcpy(xtisa_error_msg, "invalid regfile name");
1329        return XTENSA_UNDEFINED;
1330    }
1331
1332    /* The expected number of regfiles is small; use a linear search. */
1333    for (n = 0; n < intisa->num_regfiles; n++) {
1334        if (!strcmp(intisa->regfiles[n].name, name)) {
1335            return n;
1336        }
1337    }
1338
1339    xtisa_errno = xtensa_isa_bad_regfile;
1340    sprintf(xtisa_error_msg, "regfile \"%s\" not recognized", name);
1341    return XTENSA_UNDEFINED;
1342}
1343
1344
1345xtensa_regfile xtensa_regfile_lookup_shortname(xtensa_isa isa,
1346                                               const char *shortname)
1347{
1348    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1349    int n;
1350
1351    if (!shortname || !*shortname) {
1352        xtisa_errno = xtensa_isa_bad_regfile;
1353        strcpy(xtisa_error_msg, "invalid regfile shortname");
1354        return XTENSA_UNDEFINED;
1355    }
1356
1357    /* The expected number of regfiles is small; use a linear search. */
1358    for (n = 0; n < intisa->num_regfiles; n++) {
1359        /*
1360         * Ignore regfile views since they always have the same shortnames
1361         * as their parents.
1362         */
1363        if (intisa->regfiles[n].parent != n) {
1364            continue;
1365        }
1366        if (!strcmp(intisa->regfiles[n].shortname, shortname)) {
1367            return n;
1368        }
1369    }
1370
1371    xtisa_errno = xtensa_isa_bad_regfile;
1372    sprintf(xtisa_error_msg, "regfile shortname \"%s\" not recognized",
1373            shortname);
1374    return XTENSA_UNDEFINED;
1375}
1376
1377
1378const char *xtensa_regfile_name(xtensa_isa isa, xtensa_regfile rf)
1379{
1380    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1381
1382    CHECK_REGFILE(intisa, rf, NULL);
1383    return intisa->regfiles[rf].name;
1384}
1385
1386
1387const char *xtensa_regfile_shortname(xtensa_isa isa, xtensa_regfile rf)
1388{
1389    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1390
1391    CHECK_REGFILE(intisa, rf, NULL);
1392    return intisa->regfiles[rf].shortname;
1393}
1394
1395
1396xtensa_regfile xtensa_regfile_view_parent(xtensa_isa isa, xtensa_regfile rf)
1397{
1398    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1399
1400    CHECK_REGFILE(intisa, rf, XTENSA_UNDEFINED);
1401    return intisa->regfiles[rf].parent;
1402}
1403
1404
1405int xtensa_regfile_num_bits(xtensa_isa isa, xtensa_regfile rf)
1406{
1407    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1408
1409    CHECK_REGFILE(intisa, rf, XTENSA_UNDEFINED);
1410    return intisa->regfiles[rf].num_bits;
1411}
1412
1413
1414int xtensa_regfile_num_entries(xtensa_isa isa, xtensa_regfile rf)
1415{
1416    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1417
1418    CHECK_REGFILE(intisa, rf, XTENSA_UNDEFINED);
1419    return intisa->regfiles[rf].num_entries;
1420}
1421
1422
1423/* Processor States. */
1424
1425
1426#define CHECK_STATE(INTISA, ST, ERRVAL) \
1427    do { \
1428        if ((ST) < 0 || (ST) >= (INTISA)->num_states) { \
1429            xtisa_errno = xtensa_isa_bad_state; \
1430            strcpy(xtisa_error_msg, "invalid state specifier"); \
1431            return ERRVAL; \
1432        } \
1433    } while (0)
1434
1435
1436xtensa_state xtensa_state_lookup(xtensa_isa isa, const char *name)
1437{
1438    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1439    xtensa_lookup_entry entry, *result = 0;
1440
1441    if (!name || !*name) {
1442        xtisa_errno = xtensa_isa_bad_state;
1443        strcpy(xtisa_error_msg, "invalid state name");
1444        return XTENSA_UNDEFINED;
1445    }
1446
1447    if (intisa->num_states != 0) {
1448        entry.key = name;
1449        result = bsearch(&entry, intisa->state_lookup_table,
1450                         intisa->num_states, sizeof(xtensa_lookup_entry),
1451                         xtensa_isa_name_compare);
1452    }
1453
1454    if (!result) {
1455        xtisa_errno = xtensa_isa_bad_state;
1456        sprintf(xtisa_error_msg, "state \"%s\" not recognized", name);
1457        return XTENSA_UNDEFINED;
1458    }
1459
1460    return result->u.state;
1461}
1462
1463
1464const char *xtensa_state_name(xtensa_isa isa, xtensa_state st)
1465{
1466    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1467
1468    CHECK_STATE(intisa, st, NULL);
1469    return intisa->states[st].name;
1470}
1471
1472
1473int xtensa_state_num_bits(xtensa_isa isa, xtensa_state st)
1474{
1475    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1476
1477    CHECK_STATE(intisa, st, XTENSA_UNDEFINED);
1478    return intisa->states[st].num_bits;
1479}
1480
1481
1482int xtensa_state_is_exported(xtensa_isa isa, xtensa_state st)
1483{
1484    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1485
1486    CHECK_STATE(intisa, st, XTENSA_UNDEFINED);
1487    if ((intisa->states[st].flags & XTENSA_STATE_IS_EXPORTED) != 0) {
1488        return 1;
1489    }
1490    return 0;
1491}
1492
1493
1494int xtensa_state_is_shared_or(xtensa_isa isa, xtensa_state st)
1495{
1496    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1497
1498    CHECK_STATE(intisa, st, XTENSA_UNDEFINED);
1499    if ((intisa->states[st].flags & XTENSA_STATE_IS_SHARED_OR) != 0) {
1500        return 1;
1501    }
1502    return 0;
1503}
1504
1505
1506/* Sysregs. */
1507
1508
1509#define CHECK_SYSREG(INTISA, SYSREG, ERRVAL) \
1510    do { \
1511        if ((SYSREG) < 0 || (SYSREG) >= (INTISA)->num_sysregs) { \
1512            xtisa_errno = xtensa_isa_bad_sysreg; \
1513            strcpy(xtisa_error_msg, "invalid sysreg specifier"); \
1514            return ERRVAL; \
1515        } \
1516    } while (0)
1517
1518
1519xtensa_sysreg xtensa_sysreg_lookup(xtensa_isa isa, int num, int is_user)
1520{
1521    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1522
1523    if (is_user != 0) {
1524        is_user = 1;
1525    }
1526
1527    if (num < 0 || num > intisa->max_sysreg_num[is_user] ||
1528        intisa->sysreg_table[is_user][num] == XTENSA_UNDEFINED) {
1529        xtisa_errno = xtensa_isa_bad_sysreg;
1530        strcpy(xtisa_error_msg, "sysreg not recognized");
1531        return XTENSA_UNDEFINED;
1532    }
1533
1534    return intisa->sysreg_table[is_user][num];
1535}
1536
1537
1538xtensa_sysreg xtensa_sysreg_lookup_name(xtensa_isa isa, const char *name)
1539{
1540    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1541    xtensa_lookup_entry entry, *result = 0;
1542
1543    if (!name || !*name) {
1544        xtisa_errno = xtensa_isa_bad_sysreg;
1545        strcpy(xtisa_error_msg, "invalid sysreg name");
1546        return XTENSA_UNDEFINED;
1547    }
1548
1549    if (intisa->num_sysregs != 0) {
1550        entry.key = name;
1551        result = bsearch(&entry, intisa->sysreg_lookup_table,
1552                         intisa->num_sysregs, sizeof(xtensa_lookup_entry),
1553                         xtensa_isa_name_compare);
1554    }
1555
1556    if (!result) {
1557        xtisa_errno = xtensa_isa_bad_sysreg;
1558        sprintf(xtisa_error_msg, "sysreg \"%s\" not recognized", name);
1559        return XTENSA_UNDEFINED;
1560    }
1561
1562    return result->u.sysreg;
1563}
1564
1565
1566const char *xtensa_sysreg_name(xtensa_isa isa, xtensa_sysreg sysreg)
1567{
1568    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1569
1570    CHECK_SYSREG(intisa, sysreg, NULL);
1571    return intisa->sysregs[sysreg].name;
1572}
1573
1574
1575int xtensa_sysreg_number(xtensa_isa isa, xtensa_sysreg sysreg)
1576{
1577    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1578
1579    CHECK_SYSREG(intisa, sysreg, XTENSA_UNDEFINED);
1580    return intisa->sysregs[sysreg].number;
1581}
1582
1583
1584int xtensa_sysreg_is_user(xtensa_isa isa, xtensa_sysreg sysreg)
1585{
1586    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1587
1588    CHECK_SYSREG(intisa, sysreg, XTENSA_UNDEFINED);
1589    if (intisa->sysregs[sysreg].is_user) {
1590        return 1;
1591    }
1592    return 0;
1593}
1594
1595
1596/* Interfaces. */
1597
1598
1599#define CHECK_INTERFACE(INTISA, INTF, ERRVAL) \
1600    do { \
1601        if ((INTF) < 0 || (INTF) >= (INTISA)->num_interfaces) { \
1602            xtisa_errno = xtensa_isa_bad_interface; \
1603            strcpy(xtisa_error_msg, "invalid interface specifier"); \
1604            return ERRVAL; \
1605        } \
1606    } while (0)
1607
1608
1609xtensa_interface xtensa_interface_lookup(xtensa_isa isa, const char *ifname)
1610{
1611    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1612    xtensa_lookup_entry entry, *result = 0;
1613
1614    if (!ifname || !*ifname) {
1615        xtisa_errno = xtensa_isa_bad_interface;
1616        strcpy(xtisa_error_msg, "invalid interface name");
1617        return XTENSA_UNDEFINED;
1618    }
1619
1620    if (intisa->num_interfaces != 0) {
1621        entry.key = ifname;
1622        result = bsearch(&entry, intisa->interface_lookup_table,
1623                         intisa->num_interfaces, sizeof(xtensa_lookup_entry),
1624                         xtensa_isa_name_compare);
1625    }
1626
1627    if (!result) {
1628        xtisa_errno = xtensa_isa_bad_interface;
1629        sprintf(xtisa_error_msg, "interface \"%s\" not recognized", ifname);
1630        return XTENSA_UNDEFINED;
1631    }
1632
1633    return result->u.intf;
1634}
1635
1636
1637const char *xtensa_interface_name(xtensa_isa isa, xtensa_interface intf)
1638{
1639    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1640
1641    CHECK_INTERFACE(intisa, intf, NULL);
1642    return intisa->interfaces[intf].name;
1643}
1644
1645
1646int xtensa_interface_num_bits(xtensa_isa isa, xtensa_interface intf)
1647{
1648    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1649
1650    CHECK_INTERFACE(intisa, intf, XTENSA_UNDEFINED);
1651    return intisa->interfaces[intf].num_bits;
1652}
1653
1654
1655char xtensa_interface_inout(xtensa_isa isa, xtensa_interface intf)
1656{
1657    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1658
1659    CHECK_INTERFACE(intisa, intf, 0);
1660    return intisa->interfaces[intf].inout;
1661}
1662
1663
1664int xtensa_interface_has_side_effect(xtensa_isa isa, xtensa_interface intf)
1665{
1666    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1667
1668    CHECK_INTERFACE(intisa, intf, XTENSA_UNDEFINED);
1669    if ((intisa->interfaces[intf].flags &
1670         XTENSA_INTERFACE_HAS_SIDE_EFFECT) != 0) {
1671        return 1;
1672    }
1673    return 0;
1674}
1675
1676
1677int xtensa_interface_class_id(xtensa_isa isa, xtensa_interface intf)
1678{
1679    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1680
1681    CHECK_INTERFACE(intisa, intf, XTENSA_UNDEFINED);
1682    return intisa->interfaces[intf].class_id;
1683}
1684
1685
1686/* Functional Units. */
1687
1688
1689#define CHECK_FUNCUNIT(INTISA, FUN, ERRVAL) \
1690    do { \
1691        if ((FUN) < 0 || (FUN) >= (INTISA)->num_funcUnits) { \
1692            xtisa_errno = xtensa_isa_bad_funcUnit; \
1693            strcpy(xtisa_error_msg, "invalid functional unit specifier"); \
1694            return ERRVAL; \
1695        } \
1696    } while (0)
1697
1698
1699xtensa_funcUnit xtensa_funcUnit_lookup(xtensa_isa isa, const char *fname)
1700{
1701    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1702    xtensa_lookup_entry entry, *result = 0;
1703
1704    if (!fname || !*fname) {
1705        xtisa_errno = xtensa_isa_bad_funcUnit;
1706        strcpy(xtisa_error_msg, "invalid functional unit name");
1707        return XTENSA_UNDEFINED;
1708    }
1709
1710    if (intisa->num_funcUnits != 0) {
1711        entry.key = fname;
1712        result = bsearch(&entry, intisa->funcUnit_lookup_table,
1713                         intisa->num_funcUnits, sizeof(xtensa_lookup_entry),
1714                         xtensa_isa_name_compare);
1715    }
1716
1717    if (!result) {
1718        xtisa_errno = xtensa_isa_bad_funcUnit;
1719        sprintf(xtisa_error_msg,
1720                "functional unit \"%s\" not recognized", fname);
1721        return XTENSA_UNDEFINED;
1722    }
1723
1724    return result->u.fun;
1725}
1726
1727
1728const char *xtensa_funcUnit_name(xtensa_isa isa, xtensa_funcUnit fun)
1729{
1730    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1731
1732    CHECK_FUNCUNIT(intisa, fun, NULL);
1733    return intisa->funcUnits[fun].name;
1734}
1735
1736
1737int xtensa_funcUnit_num_copies(xtensa_isa isa, xtensa_funcUnit fun)
1738{
1739    xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1740
1741    CHECK_FUNCUNIT(intisa, fun, XTENSA_UNDEFINED);
1742    return intisa->funcUnits[fun].num_copies;
1743}
1744