cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

decode.c (29817B)


      1/*
      2 *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
      3 *
      4 *  This program is free software; you can redistribute it and/or modify
      5 *  it under the terms of the GNU General Public License as published by
      6 *  the Free Software Foundation; either version 2 of the License, or
      7 *  (at your option) any later version.
      8 *
      9 *  This program is distributed in the hope that it will be useful,
     10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 *  GNU General Public License for more details.
     13 *
     14 *  You should have received a copy of the GNU General Public License
     15 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#include "qemu/osdep.h"
     19#include "iclass.h"
     20#include "attribs.h"
     21#include "genptr.h"
     22#include "decode.h"
     23#include "insn.h"
     24#include "printinsn.h"
     25
     26#define fZXTN(N, M, VAL) ((VAL) & ((1LL << (N)) - 1))
     27
     28enum {
     29    EXT_IDX_noext = 0,
     30    EXT_IDX_noext_AFTER = 4,
     31    EXT_IDX_mmvec = 4,
     32    EXT_IDX_mmvec_AFTER = 8,
     33    XX_LAST_EXT_IDX
     34};
     35
     36/*
     37 *  Certain operand types represent a non-contiguous set of values.
     38 *  For example, the compound compare-and-jump instruction can only access
     39 *  registers R0-R7 and R16-23.
     40 *  This table represents the mapping from the encoding to the actual values.
     41 */
     42
     43#define DEF_REGMAP(NAME, ELEMENTS, ...) \
     44    static const unsigned int DECODE_REGISTER_##NAME[ELEMENTS] = \
     45    { __VA_ARGS__ };
     46        /* Name   Num Table */
     47DEF_REGMAP(R_16,  16, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23)
     48DEF_REGMAP(R__8,  8,  0, 2, 4, 6, 16, 18, 20, 22)
     49
     50#define DECODE_MAPPED_REG(OPNUM, NAME) \
     51    insn->regno[OPNUM] = DECODE_REGISTER_##NAME[insn->regno[OPNUM]];
     52
     53typedef struct {
     54    const struct DectreeTable *table_link;
     55    const struct DectreeTable *table_link_b;
     56    Opcode opcode;
     57    enum {
     58        DECTREE_ENTRY_INVALID,
     59        DECTREE_TABLE_LINK,
     60        DECTREE_SUBINSNS,
     61        DECTREE_EXTSPACE,
     62        DECTREE_TERMINAL
     63    } type;
     64} DectreeEntry;
     65
     66typedef struct DectreeTable {
     67    unsigned int (*lookup_function)(int startbit, int width, uint32_t opcode);
     68    unsigned int size;
     69    unsigned int startbit;
     70    unsigned int width;
     71    const DectreeEntry table[];
     72} DectreeTable;
     73
     74#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
     75    static const DectreeTable dectree_table_##TAG;
     76#define TABLE_LINK(TABLE)                     /* NOTHING */
     77#define TERMINAL(TAG, ENC)                    /* NOTHING */
     78#define SUBINSNS(TAG, CLASSA, CLASSB, ENC)    /* NOTHING */
     79#define EXTSPACE(TAG, ENC)                    /* NOTHING */
     80#define INVALID()                             /* NOTHING */
     81#define DECODE_END_TABLE(...)                 /* NOTHING */
     82#define DECODE_MATCH_INFO(...)                /* NOTHING */
     83#define DECODE_LEGACY_MATCH_INFO(...)         /* NOTHING */
     84#define DECODE_OPINFO(...)                    /* NOTHING */
     85
     86#include "dectree_generated.h.inc"
     87
     88#undef DECODE_OPINFO
     89#undef DECODE_MATCH_INFO
     90#undef DECODE_LEGACY_MATCH_INFO
     91#undef DECODE_END_TABLE
     92#undef INVALID
     93#undef TERMINAL
     94#undef SUBINSNS
     95#undef EXTSPACE
     96#undef TABLE_LINK
     97#undef DECODE_NEW_TABLE
     98#undef DECODE_SEPARATOR_BITS
     99
    100#define DECODE_SEPARATOR_BITS(START, WIDTH) NULL, START, WIDTH
    101#define DECODE_NEW_TABLE_HELPER(TAG, SIZE, FN, START, WIDTH) \
    102    static const DectreeTable dectree_table_##TAG = { \
    103        .size = SIZE, \
    104        .lookup_function = FN, \
    105        .startbit = START, \
    106        .width = WIDTH, \
    107        .table = {
    108#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
    109    DECODE_NEW_TABLE_HELPER(TAG, SIZE, WHATNOT)
    110
    111#define TABLE_LINK(TABLE) \
    112    { .type = DECTREE_TABLE_LINK, .table_link = &dectree_table_##TABLE },
    113#define TERMINAL(TAG, ENC) \
    114    { .type = DECTREE_TERMINAL, .opcode = TAG  },
    115#define SUBINSNS(TAG, CLASSA, CLASSB, ENC) \
    116    { \
    117        .type = DECTREE_SUBINSNS, \
    118        .table_link = &dectree_table_DECODE_SUBINSN_##CLASSA, \
    119        .table_link_b = &dectree_table_DECODE_SUBINSN_##CLASSB \
    120    },
    121#define EXTSPACE(TAG, ENC) { .type = DECTREE_EXTSPACE },
    122#define INVALID() { .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
    123
    124#define DECODE_END_TABLE(...) } };
    125
    126#define DECODE_MATCH_INFO(...)                /* NOTHING */
    127#define DECODE_LEGACY_MATCH_INFO(...)         /* NOTHING */
    128#define DECODE_OPINFO(...)                    /* NOTHING */
    129
    130#include "dectree_generated.h.inc"
    131
    132#undef DECODE_OPINFO
    133#undef DECODE_MATCH_INFO
    134#undef DECODE_LEGACY_MATCH_INFO
    135#undef DECODE_END_TABLE
    136#undef INVALID
    137#undef TERMINAL
    138#undef SUBINSNS
    139#undef EXTSPACE
    140#undef TABLE_LINK
    141#undef DECODE_NEW_TABLE
    142#undef DECODE_NEW_TABLE_HELPER
    143#undef DECODE_SEPARATOR_BITS
    144
    145static const DectreeTable dectree_table_DECODE_EXT_EXT_noext = {
    146    .size = 1, .lookup_function = NULL, .startbit = 0, .width = 0,
    147    .table = {
    148        { .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
    149    }
    150};
    151
    152static const DectreeTable *ext_trees[XX_LAST_EXT_IDX];
    153
    154static void decode_ext_init(void)
    155{
    156    int i;
    157    for (i = EXT_IDX_noext; i < EXT_IDX_noext_AFTER; i++) {
    158        ext_trees[i] = &dectree_table_DECODE_EXT_EXT_noext;
    159    }
    160}
    161
    162typedef struct {
    163    uint32_t mask;
    164    uint32_t match;
    165} DecodeITableEntry;
    166
    167#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT)  /* NOTHING */
    168#define TABLE_LINK(TABLE)                     /* NOTHING */
    169#define TERMINAL(TAG, ENC)                    /* NOTHING */
    170#define SUBINSNS(TAG, CLASSA, CLASSB, ENC)    /* NOTHING */
    171#define EXTSPACE(TAG, ENC)                    /* NOTHING */
    172#define INVALID()                             /* NOTHING */
    173#define DECODE_END_TABLE(...)                 /* NOTHING */
    174#define DECODE_OPINFO(...)                    /* NOTHING */
    175
    176#define DECODE_MATCH_INFO_NORMAL(TAG, MASK, MATCH) \
    177    [TAG] = { \
    178        .mask = MASK, \
    179        .match = MATCH, \
    180    },
    181
    182#define DECODE_MATCH_INFO_NULL(TAG, MASK, MATCH) \
    183    [TAG] = { .match = ~0 },
    184
    185#define DECODE_MATCH_INFO(...) DECODE_MATCH_INFO_NORMAL(__VA_ARGS__)
    186#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
    187
    188static const DecodeITableEntry decode_itable[XX_LAST_OPCODE] = {
    189#include "dectree_generated.h.inc"
    190};
    191
    192#undef DECODE_MATCH_INFO
    193#define DECODE_MATCH_INFO(...) DECODE_MATCH_INFO_NULL(__VA_ARGS__)
    194
    195#undef DECODE_LEGACY_MATCH_INFO
    196#define DECODE_LEGACY_MATCH_INFO(...) DECODE_MATCH_INFO_NORMAL(__VA_ARGS__)
    197
    198static const DecodeITableEntry decode_legacy_itable[XX_LAST_OPCODE] = {
    199#include "dectree_generated.h.inc"
    200};
    201
    202#undef DECODE_OPINFO
    203#undef DECODE_MATCH_INFO
    204#undef DECODE_LEGACY_MATCH_INFO
    205#undef DECODE_END_TABLE
    206#undef INVALID
    207#undef TERMINAL
    208#undef SUBINSNS
    209#undef EXTSPACE
    210#undef TABLE_LINK
    211#undef DECODE_NEW_TABLE
    212#undef DECODE_SEPARATOR_BITS
    213
    214void decode_init(void)
    215{
    216    decode_ext_init();
    217}
    218
    219void decode_send_insn_to(Packet *packet, int start, int newloc)
    220{
    221    Insn tmpinsn;
    222    int direction;
    223    int i;
    224    if (start == newloc) {
    225        return;
    226    }
    227    if (start < newloc) {
    228        /* Move towards end */
    229        direction = 1;
    230    } else {
    231        /* move towards beginning */
    232        direction = -1;
    233    }
    234    for (i = start; i != newloc; i += direction) {
    235        tmpinsn = packet->insn[i];
    236        packet->insn[i] = packet->insn[i + direction];
    237        packet->insn[i + direction] = tmpinsn;
    238    }
    239}
    240
    241/* Fill newvalue registers with the correct regno */
    242static void
    243decode_fill_newvalue_regno(Packet *packet)
    244{
    245    int i, use_regidx, offset, def_idx, dst_idx;
    246    uint16_t def_opcode, use_opcode;
    247    char *dststr;
    248
    249    for (i = 1; i < packet->num_insns; i++) {
    250        if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE) &&
    251            !GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION)) {
    252            use_opcode = packet->insn[i].opcode;
    253
    254            /* It's a store, so we're adjusting the Nt field */
    255            if (GET_ATTRIB(use_opcode, A_STORE)) {
    256                use_regidx = strchr(opcode_reginfo[use_opcode], 't') -
    257                    opcode_reginfo[use_opcode];
    258            } else {    /* It's a Jump, so we're adjusting the Ns field */
    259                use_regidx = strchr(opcode_reginfo[use_opcode], 's') -
    260                    opcode_reginfo[use_opcode];
    261            }
    262
    263            /*
    264             * What's encoded at the N-field is the offset to who's producing
    265             * the value.  Shift off the LSB which indicates odd/even register,
    266             * then walk backwards and skip over the constant extenders.
    267             */
    268            offset = packet->insn[i].regno[use_regidx] >> 1;
    269            def_idx = i - offset;
    270            for (int j = 0; j < offset; j++) {
    271                if (GET_ATTRIB(packet->insn[i - j - 1].opcode, A_IT_EXTENDER)) {
    272                    def_idx--;
    273                }
    274            }
    275
    276            /*
    277             * Check for a badly encoded N-field which points to an instruction
    278             * out-of-range
    279             */
    280            g_assert(!((def_idx < 0) || (def_idx > (packet->num_insns - 1))));
    281
    282            /*
    283             * packet->insn[def_idx] is the producer
    284             * Figure out which type of destination it produces
    285             * and the corresponding index in the reginfo
    286             */
    287            def_opcode = packet->insn[def_idx].opcode;
    288            dststr = strstr(opcode_wregs[def_opcode], "Rd");
    289            if (dststr) {
    290                dststr = strchr(opcode_reginfo[def_opcode], 'd');
    291            } else {
    292                dststr = strstr(opcode_wregs[def_opcode], "Rx");
    293                if (dststr) {
    294                    dststr = strchr(opcode_reginfo[def_opcode], 'x');
    295                } else {
    296                    dststr = strstr(opcode_wregs[def_opcode], "Re");
    297                    if (dststr) {
    298                        dststr = strchr(opcode_reginfo[def_opcode], 'e');
    299                    } else {
    300                        dststr = strstr(opcode_wregs[def_opcode], "Ry");
    301                        if (dststr) {
    302                            dststr = strchr(opcode_reginfo[def_opcode], 'y');
    303                        } else {
    304                            g_assert_not_reached();
    305                        }
    306                    }
    307                }
    308            }
    309            g_assert(dststr != NULL);
    310
    311            /* Now patch up the consumer with the register number */
    312            dst_idx = dststr - opcode_reginfo[def_opcode];
    313            packet->insn[i].regno[use_regidx] =
    314                packet->insn[def_idx].regno[dst_idx];
    315            /*
    316             * We need to remember who produces this value to later
    317             * check if it was dynamically cancelled
    318             */
    319            packet->insn[i].new_value_producer_slot =
    320                packet->insn[def_idx].slot;
    321        }
    322    }
    323}
    324
    325/* Split CJ into a compare and a jump */
    326static void decode_split_cmpjump(Packet *pkt)
    327{
    328    int last, i;
    329    int numinsns = pkt->num_insns;
    330
    331    /*
    332     * First, split all compare-jumps.
    333     * The compare is sent to the end as a new instruction.
    334     * Do it this way so we don't reorder dual jumps. Those need to stay in
    335     * original order.
    336     */
    337    for (i = 0; i < numinsns; i++) {
    338        /* It's a cmp-jump */
    339        if (GET_ATTRIB(pkt->insn[i].opcode, A_NEWCMPJUMP)) {
    340            last = pkt->num_insns;
    341            pkt->insn[last] = pkt->insn[i];    /* copy the instruction */
    342            pkt->insn[last].part1 = true;      /* last insn does the CMP */
    343            pkt->insn[i].part1 = false;        /* existing insn does the JUMP */
    344            pkt->num_insns++;
    345        }
    346    }
    347
    348    /* Now re-shuffle all the compares back to the beginning */
    349    for (i = 0; i < pkt->num_insns; i++) {
    350        if (pkt->insn[i].part1) {
    351            decode_send_insn_to(pkt, i, 0);
    352        }
    353    }
    354}
    355
    356static bool decode_opcode_can_jump(int opcode)
    357{
    358    if ((GET_ATTRIB(opcode, A_JUMP)) ||
    359        (GET_ATTRIB(opcode, A_CALL)) ||
    360        (opcode == J2_trap0) ||
    361        (opcode == J2_pause)) {
    362        /* Exception to A_JUMP attribute */
    363        if (opcode == J4_hintjumpr) {
    364            return false;
    365        }
    366        return true;
    367    }
    368
    369    return false;
    370}
    371
    372static bool decode_opcode_ends_loop(int opcode)
    373{
    374    return GET_ATTRIB(opcode, A_HWLOOP0_END) ||
    375           GET_ATTRIB(opcode, A_HWLOOP1_END);
    376}
    377
    378/* Set the is_* fields in each instruction */
    379static void decode_set_insn_attr_fields(Packet *pkt)
    380{
    381    int i;
    382    int numinsns = pkt->num_insns;
    383    uint16_t opcode;
    384
    385    pkt->pkt_has_cof = false;
    386    pkt->pkt_has_endloop = false;
    387    pkt->pkt_has_dczeroa = false;
    388
    389    for (i = 0; i < numinsns; i++) {
    390        opcode = pkt->insn[i].opcode;
    391        if (pkt->insn[i].part1) {
    392            continue;    /* Skip compare of cmp-jumps */
    393        }
    394
    395        if (GET_ATTRIB(opcode, A_DCZEROA)) {
    396            pkt->pkt_has_dczeroa = true;
    397        }
    398
    399        if (GET_ATTRIB(opcode, A_STORE)) {
    400            if (pkt->insn[i].slot == 0) {
    401                pkt->pkt_has_store_s0 = true;
    402            } else {
    403                pkt->pkt_has_store_s1 = true;
    404            }
    405        }
    406
    407        pkt->pkt_has_cof |= decode_opcode_can_jump(opcode);
    408
    409        pkt->insn[i].is_endloop = decode_opcode_ends_loop(opcode);
    410
    411        pkt->pkt_has_endloop |= pkt->insn[i].is_endloop;
    412
    413        pkt->pkt_has_cof |= pkt->pkt_has_endloop;
    414    }
    415}
    416
    417/*
    418 * Shuffle for execution
    419 * Move stores to end (in same order as encoding)
    420 * Move compares to beginning (for use by .new insns)
    421 */
    422static void decode_shuffle_for_execution(Packet *packet)
    423{
    424    bool changed = false;
    425    int i;
    426    bool flag;    /* flag means we've seen a non-memory instruction */
    427    int n_mems;
    428    int last_insn = packet->num_insns - 1;
    429
    430    /*
    431     * Skip end loops, somehow an end loop is getting in and messing
    432     * up the order
    433     */
    434    if (decode_opcode_ends_loop(packet->insn[last_insn].opcode)) {
    435        last_insn--;
    436    }
    437
    438    do {
    439        changed = false;
    440        /*
    441         * Stores go last, must not reorder.
    442         * Cannot shuffle stores past loads, either.
    443         * Iterate backwards.  If we see a non-memory instruction,
    444         * then a store, shuffle the store to the front.  Don't shuffle
    445         * stores wrt each other or a load.
    446         */
    447        for (flag = false, n_mems = 0, i = last_insn; i >= 0; i--) {
    448            int opcode = packet->insn[i].opcode;
    449
    450            if (flag && GET_ATTRIB(opcode, A_STORE)) {
    451                decode_send_insn_to(packet, i, last_insn - n_mems);
    452                n_mems++;
    453                changed = true;
    454            } else if (GET_ATTRIB(opcode, A_STORE)) {
    455                n_mems++;
    456            } else if (GET_ATTRIB(opcode, A_LOAD)) {
    457                /*
    458                 * Don't set flag, since we don't want to shuffle a
    459                 * store past a load
    460                 */
    461                n_mems++;
    462            } else if (GET_ATTRIB(opcode, A_DOTNEWVALUE)) {
    463                /*
    464                 * Don't set flag, since we don't want to shuffle past
    465                 * a .new value
    466                 */
    467            } else {
    468                flag = true;
    469            }
    470        }
    471
    472        if (changed) {
    473            continue;
    474        }
    475        /* Compares go first, may be reordered wrt each other */
    476        for (flag = false, i = 0; i < last_insn + 1; i++) {
    477            int opcode = packet->insn[i].opcode;
    478
    479            if ((strstr(opcode_wregs[opcode], "Pd4") ||
    480                 strstr(opcode_wregs[opcode], "Pe4")) &&
    481                GET_ATTRIB(opcode, A_STORE) == 0) {
    482                /* This should be a compare (not a store conditional) */
    483                if (flag) {
    484                    decode_send_insn_to(packet, i, 0);
    485                    changed = true;
    486                    continue;
    487                }
    488            } else if (GET_ATTRIB(opcode, A_IMPLICIT_WRITES_P3) &&
    489                       !decode_opcode_ends_loop(packet->insn[i].opcode)) {
    490                /*
    491                 * spNloop instruction
    492                 * Don't reorder endloops; they are not valid for .new uses,
    493                 * and we want to match HW
    494                 */
    495                if (flag) {
    496                    decode_send_insn_to(packet, i, 0);
    497                    changed = true;
    498                    continue;
    499                }
    500            } else if (GET_ATTRIB(opcode, A_IMPLICIT_WRITES_P0) &&
    501                       !GET_ATTRIB(opcode, A_NEWCMPJUMP)) {
    502                if (flag) {
    503                    decode_send_insn_to(packet, i, 0);
    504                    changed = true;
    505                    continue;
    506                }
    507            } else {
    508                flag = true;
    509            }
    510        }
    511        if (changed) {
    512            continue;
    513        }
    514    } while (changed);
    515
    516    /*
    517     * If we have a .new register compare/branch, move that to the very
    518     * very end, past stores
    519     */
    520    for (i = 0; i < last_insn; i++) {
    521        if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE)) {
    522            decode_send_insn_to(packet, i, last_insn);
    523            break;
    524        }
    525    }
    526}
    527
    528static void
    529apply_extender(Packet *pkt, int i, uint32_t extender)
    530{
    531    int immed_num;
    532    uint32_t base_immed;
    533
    534    immed_num = opcode_which_immediate_is_extended(pkt->insn[i].opcode);
    535    base_immed = pkt->insn[i].immed[immed_num];
    536
    537    pkt->insn[i].immed[immed_num] = extender | fZXTN(6, 32, base_immed);
    538}
    539
    540static void decode_apply_extenders(Packet *packet)
    541{
    542    int i;
    543    for (i = 0; i < packet->num_insns; i++) {
    544        if (GET_ATTRIB(packet->insn[i].opcode, A_IT_EXTENDER)) {
    545            packet->insn[i + 1].extension_valid = true;
    546            apply_extender(packet, i + 1, packet->insn[i].immed[0]);
    547        }
    548    }
    549}
    550
    551static void decode_remove_extenders(Packet *packet)
    552{
    553    int i, j;
    554    for (i = 0; i < packet->num_insns; i++) {
    555        if (GET_ATTRIB(packet->insn[i].opcode, A_IT_EXTENDER)) {
    556            /* Remove this one by moving the remaining instructions down */
    557            for (j = i;
    558                (j < packet->num_insns - 1) && (j < INSTRUCTIONS_MAX - 1);
    559                j++) {
    560                packet->insn[j] = packet->insn[j + 1];
    561            }
    562            packet->num_insns--;
    563        }
    564    }
    565}
    566
    567static SlotMask get_valid_slots(const Packet *pkt, unsigned int slot)
    568{
    569    return find_iclass_slots(pkt->insn[slot].opcode,
    570                             pkt->insn[slot].iclass);
    571}
    572
    573#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT)     /* NOTHING */
    574#define TABLE_LINK(TABLE)                        /* NOTHING */
    575#define TERMINAL(TAG, ENC)                       /* NOTHING */
    576#define SUBINSNS(TAG, CLASSA, CLASSB, ENC)       /* NOTHING */
    577#define EXTSPACE(TAG, ENC)                       /* NOTHING */
    578#define INVALID()                                /* NOTHING */
    579#define DECODE_END_TABLE(...)                    /* NOTHING */
    580#define DECODE_MATCH_INFO(...)                   /* NOTHING */
    581#define DECODE_LEGACY_MATCH_INFO(...)            /* NOTHING */
    582
    583#define DECODE_REG(REGNO, WIDTH, STARTBIT) \
    584    insn->regno[REGNO] = ((encoding >> STARTBIT) & ((1 << WIDTH) - 1));
    585
    586#define DECODE_IMPL_REG(REGNO, VAL) \
    587    insn->regno[REGNO] = VAL;
    588
    589#define DECODE_IMM(IMMNO, WIDTH, STARTBIT, VALSTART) \
    590    insn->immed[IMMNO] |= (((encoding >> STARTBIT) & ((1 << WIDTH) - 1))) << \
    591                          (VALSTART);
    592
    593#define DECODE_IMM_SXT(IMMNO, WIDTH) \
    594    insn->immed[IMMNO] = ((((int32_t)insn->immed[IMMNO]) << (32 - WIDTH)) >> \
    595                          (32 - WIDTH));
    596
    597#define DECODE_IMM_NEG(IMMNO, WIDTH) \
    598    insn->immed[IMMNO] = -insn->immed[IMMNO];
    599
    600#define DECODE_IMM_SHIFT(IMMNO, SHAMT)                                 \
    601    if ((!insn->extension_valid) || \
    602        (insn->which_extended != IMMNO)) { \
    603        insn->immed[IMMNO] <<= SHAMT; \
    604    }
    605
    606#define DECODE_OPINFO(TAG, BEH) \
    607    case TAG: \
    608        { BEH  } \
    609        break; \
    610
    611/*
    612 * Fill in the operands of the instruction
    613 * dectree_generated.h.inc has a DECODE_OPINFO entry for each opcode
    614 * For example,
    615 *     DECODE_OPINFO(A2_addi,
    616 *          DECODE_REG(0,5,0)
    617 *          DECODE_REG(1,5,16)
    618 *          DECODE_IMM(0,7,21,9)
    619 *          DECODE_IMM(0,9,5,0)
    620 *          DECODE_IMM_SXT(0,16)
    621 * with the macros defined above, we'll fill in a switch statement
    622 * where each case is an opcode tag.
    623 */
    624static void
    625decode_op(Insn *insn, Opcode tag, uint32_t encoding)
    626{
    627    insn->immed[0] = 0;
    628    insn->immed[1] = 0;
    629    insn->opcode = tag;
    630    if (insn->extension_valid) {
    631        insn->which_extended = opcode_which_immediate_is_extended(tag);
    632    }
    633
    634    switch (tag) {
    635#include "dectree_generated.h.inc"
    636    default:
    637        break;
    638    }
    639
    640    insn->generate = opcode_genptr[tag];
    641
    642    insn->iclass = iclass_bits(encoding);
    643}
    644
    645#undef DECODE_REG
    646#undef DECODE_IMPL_REG
    647#undef DECODE_IMM
    648#undef DECODE_IMM_SHIFT
    649#undef DECODE_OPINFO
    650#undef DECODE_MATCH_INFO
    651#undef DECODE_LEGACY_MATCH_INFO
    652#undef DECODE_END_TABLE
    653#undef INVALID
    654#undef TERMINAL
    655#undef SUBINSNS
    656#undef EXTSPACE
    657#undef TABLE_LINK
    658#undef DECODE_NEW_TABLE
    659#undef DECODE_SEPARATOR_BITS
    660
    661static unsigned int
    662decode_subinsn_tablewalk(Insn *insn, const DectreeTable *table,
    663                         uint32_t encoding)
    664{
    665    unsigned int i;
    666    Opcode opc;
    667    if (table->lookup_function) {
    668        i = table->lookup_function(table->startbit, table->width, encoding);
    669    } else {
    670        i = extract32(encoding, table->startbit, table->width);
    671    }
    672    if (table->table[i].type == DECTREE_TABLE_LINK) {
    673        return decode_subinsn_tablewalk(insn, table->table[i].table_link,
    674                                        encoding);
    675    } else if (table->table[i].type == DECTREE_TERMINAL) {
    676        opc = table->table[i].opcode;
    677        if ((encoding & decode_itable[opc].mask) != decode_itable[opc].match) {
    678            return 0;
    679        }
    680        decode_op(insn, opc, encoding);
    681        return 1;
    682    } else {
    683        return 0;
    684    }
    685}
    686
    687static unsigned int get_insn_a(uint32_t encoding)
    688{
    689    return extract32(encoding, 0, 13);
    690}
    691
    692static unsigned int get_insn_b(uint32_t encoding)
    693{
    694    return extract32(encoding, 16, 13);
    695}
    696
    697static unsigned int
    698decode_insns_tablewalk(Insn *insn, const DectreeTable *table,
    699                       uint32_t encoding)
    700{
    701    unsigned int i;
    702    unsigned int a, b;
    703    Opcode opc;
    704    if (table->lookup_function) {
    705        i = table->lookup_function(table->startbit, table->width, encoding);
    706    } else {
    707        i = extract32(encoding, table->startbit, table->width);
    708    }
    709    if (table->table[i].type == DECTREE_TABLE_LINK) {
    710        return decode_insns_tablewalk(insn, table->table[i].table_link,
    711                                      encoding);
    712    } else if (table->table[i].type == DECTREE_SUBINSNS) {
    713        a = get_insn_a(encoding);
    714        b = get_insn_b(encoding);
    715        b = decode_subinsn_tablewalk(insn, table->table[i].table_link_b, b);
    716        a = decode_subinsn_tablewalk(insn + 1, table->table[i].table_link, a);
    717        if ((a == 0) || (b == 0)) {
    718            return 0;
    719        }
    720        return 2;
    721    } else if (table->table[i].type == DECTREE_TERMINAL) {
    722        opc = table->table[i].opcode;
    723        if ((encoding & decode_itable[opc].mask) != decode_itable[opc].match) {
    724            if ((encoding & decode_legacy_itable[opc].mask) !=
    725                decode_legacy_itable[opc].match) {
    726                return 0;
    727            }
    728        }
    729        decode_op(insn, opc, encoding);
    730        return 1;
    731    } else {
    732        return 0;
    733    }
    734}
    735
    736static unsigned int
    737decode_insns(Insn *insn, uint32_t encoding)
    738{
    739    const DectreeTable *table;
    740    if (parse_bits(encoding) != 0) {
    741        /* Start with PP table - 32 bit instructions */
    742        table = &dectree_table_DECODE_ROOT_32;
    743    } else {
    744        /* start with EE table - duplex instructions */
    745        table = &dectree_table_DECODE_ROOT_EE;
    746    }
    747    return decode_insns_tablewalk(insn, table, encoding);
    748}
    749
    750static void decode_add_endloop_insn(Insn *insn, int loopnum)
    751{
    752    if (loopnum == 10) {
    753        insn->opcode = J2_endloop01;
    754        insn->generate = opcode_genptr[J2_endloop01];
    755    } else if (loopnum == 1) {
    756        insn->opcode = J2_endloop1;
    757        insn->generate = opcode_genptr[J2_endloop1];
    758    } else if (loopnum == 0) {
    759        insn->opcode = J2_endloop0;
    760        insn->generate = opcode_genptr[J2_endloop0];
    761    } else {
    762        g_assert_not_reached();
    763    }
    764}
    765
    766static bool decode_parsebits_is_loopend(uint32_t encoding32)
    767{
    768    uint32_t bits = parse_bits(encoding32);
    769    return bits == 0x2;
    770}
    771
    772static void
    773decode_set_slot_number(Packet *pkt)
    774{
    775    int slot;
    776    int i;
    777    bool hit_mem_insn = false;
    778    bool hit_duplex = false;
    779    bool slot0_found = false;
    780    bool slot1_found = false;
    781    int slot1_iidx = 0;
    782
    783    /*
    784     * The slots are encoded in reverse order
    785     * For each instruction, count down until you find a suitable slot
    786     */
    787    for (i = 0, slot = 3; i < pkt->num_insns; i++) {
    788        SlotMask valid_slots = get_valid_slots(pkt, i);
    789
    790        while (!(valid_slots & (1 << slot))) {
    791            slot--;
    792        }
    793        pkt->insn[i].slot = slot;
    794        if (slot) {
    795            /* I've assigned the slot, now decrement it for the next insn */
    796            slot--;
    797        }
    798    }
    799
    800    /* Fix the exceptions - mem insns to slot 0,1 */
    801    for (i = pkt->num_insns - 1; i >= 0; i--) {
    802        /* First memory instruction always goes to slot 0 */
    803        if ((GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE) ||
    804             GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE_PACKET_RULES)) &&
    805            !hit_mem_insn) {
    806            hit_mem_insn = true;
    807            pkt->insn[i].slot = 0;
    808            continue;
    809        }
    810
    811        /* Next memory instruction always goes to slot 1 */
    812        if ((GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE) ||
    813             GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE_PACKET_RULES)) &&
    814            hit_mem_insn) {
    815            pkt->insn[i].slot = 1;
    816        }
    817    }
    818
    819    /* Fix the exceptions - duplex always slot 0,1 */
    820    for (i = pkt->num_insns - 1; i >= 0; i--) {
    821        /* First subinsn always goes to slot 0 */
    822        if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN) && !hit_duplex) {
    823            hit_duplex = true;
    824            pkt->insn[i].slot = 0;
    825            continue;
    826        }
    827
    828        /* Next subinsn always goes to slot 1 */
    829        if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN) && hit_duplex) {
    830            pkt->insn[i].slot = 1;
    831        }
    832    }
    833
    834    /* Fix the exceptions - slot 1 is never empty, always aligns to slot 0 */
    835    for (i = pkt->num_insns - 1; i >= 0; i--) {
    836        /* Is slot0 used? */
    837        if (pkt->insn[i].slot == 0) {
    838            bool is_endloop = (pkt->insn[i].opcode == J2_endloop01);
    839            is_endloop |= (pkt->insn[i].opcode == J2_endloop0);
    840            is_endloop |= (pkt->insn[i].opcode == J2_endloop1);
    841
    842            /*
    843             * Make sure it's not endloop since, we're overloading
    844             * slot0 for endloop
    845             */
    846            if (!is_endloop) {
    847                slot0_found = true;
    848            }
    849        }
    850        /* Is slot1 used? */
    851        if (pkt->insn[i].slot == 1) {
    852            slot1_found = true;
    853            slot1_iidx = i;
    854        }
    855    }
    856    /* Is slot0 empty and slot1 used? */
    857    if ((!slot0_found) && slot1_found) {
    858        /* Then push it to slot0 */
    859        pkt->insn[slot1_iidx].slot = 0;
    860    }
    861}
    862
    863/*
    864 * decode_packet
    865 * Decodes packet with given words
    866 * Returns 0 on insufficient words,
    867 * or number of words used on success
    868 */
    869
    870int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
    871                  bool disas_only)
    872{
    873    int num_insns = 0;
    874    int words_read = 0;
    875    bool end_of_packet = false;
    876    int new_insns = 0;
    877    uint32_t encoding32;
    878
    879    /* Initialize */
    880    memset(pkt, 0, sizeof(*pkt));
    881    /* Try to build packet */
    882    while (!end_of_packet && (words_read < max_words)) {
    883        encoding32 = words[words_read];
    884        end_of_packet = is_packet_end(encoding32);
    885        new_insns = decode_insns(&pkt->insn[num_insns], encoding32);
    886        g_assert(new_insns > 0);
    887        /*
    888         * If we saw an extender, mark next word extended so immediate
    889         * decode works
    890         */
    891        if (pkt->insn[num_insns].opcode == A4_ext) {
    892            pkt->insn[num_insns + 1].extension_valid = true;
    893        }
    894        num_insns += new_insns;
    895        words_read++;
    896    }
    897
    898    pkt->num_insns = num_insns;
    899    if (!end_of_packet) {
    900        /* Ran out of words! */
    901        return 0;
    902    }
    903    pkt->encod_pkt_size_in_bytes = words_read * 4;
    904
    905    /*
    906     * Check for :endloop in the parse bits
    907     * Section 10.6 of the Programmer's Reference describes the encoding
    908     *     The end of hardware loop 0 can be encoded with 2 words
    909     *     The end of hardware loop 1 needs 3 words
    910     */
    911    if ((words_read == 2) && (decode_parsebits_is_loopend(words[0]))) {
    912        decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 0);
    913    }
    914    if (words_read >= 3) {
    915        bool has_loop0, has_loop1;
    916        has_loop0 = decode_parsebits_is_loopend(words[0]);
    917        has_loop1 = decode_parsebits_is_loopend(words[1]);
    918        if (has_loop0 && has_loop1) {
    919            decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 10);
    920        } else if (has_loop1) {
    921            decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 1);
    922        } else if (has_loop0) {
    923            decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 0);
    924        }
    925    }
    926
    927    decode_apply_extenders(pkt);
    928    if (!disas_only) {
    929        decode_remove_extenders(pkt);
    930    }
    931    decode_set_slot_number(pkt);
    932    decode_fill_newvalue_regno(pkt);
    933
    934    if (!disas_only) {
    935        decode_shuffle_for_execution(pkt);
    936        decode_split_cmpjump(pkt);
    937        decode_set_insn_attr_fields(pkt);
    938    }
    939
    940    return words_read;
    941}
    942
    943/* Used for "-d in_asm" logging */
    944int disassemble_hexagon(uint32_t *words, int nwords, bfd_vma pc,
    945                        GString *buf)
    946{
    947    Packet pkt;
    948
    949    if (decode_packet(nwords, words, &pkt, true) > 0) {
    950        snprint_a_pkt_disas(buf, &pkt, words, pc);
    951        return pkt.encod_pkt_size_in_bytes;
    952    } else {
    953        g_string_assign(buf, "<invalid>");
    954        return 0;
    955    }
    956}