/*
 *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include "qemu/osdep.h"
#include "decode.h"
#include "opcodes.h"
#include "insn.h"
#include "iclass.h"
#include "mmvec/mmvec.h"
#include "mmvec/decode_ext_mmvec.h"

static void
check_new_value(Packet *pkt)
{
    /* .new value for a MMVector store */
    int i, j;
    const char *reginfo;
    const char *destletters;
    const char *dststr = NULL;
    uint16_t def_opcode;
    char letter;

    for (i = 1; i < pkt->num_insns; i++) {
        uint16_t use_opcode = pkt->insn[i].opcode;
        if (GET_ATTRIB(use_opcode, A_DOTNEWVALUE) &&
            GET_ATTRIB(use_opcode, A_CVI) &&
            GET_ATTRIB(use_opcode, A_STORE)) {
            int use_regidx = strchr(opcode_reginfo[use_opcode], 's') -
                opcode_reginfo[use_opcode];
            g_assert(pkt->insn[i].new_read_idx != -1 &&
                     pkt->insn[i].new_read_idx == use_regidx);
            /*
             * What's encoded at the N-field is the offset to who's producing
             * the value.
             * Shift off the LSB which indicates odd/even register.
             */
            int def_off = ((pkt->insn[i].regno[use_regidx]) >> 1);
            int def_oreg = pkt->insn[i].regno[use_regidx] & 1;
            int def_idx = -1;
            for (j = i - 1; (j >= 0) && (def_off >= 0); j--) {
                if (!GET_ATTRIB(pkt->insn[j].opcode, A_CVI)) {
                    continue;
                }
                def_off--;
                if (def_off == 0) {
                    def_idx = j;
                    break;
                }
            }
            /*
             * Check for a badly encoded N-field which points to an instruction
             * out-of-range
             */
            g_assert(!((def_off != 0) || (def_idx < 0) ||
                       (def_idx > (pkt->num_insns - 1))));

            /* def_idx is the index of the producer */
            def_opcode = pkt->insn[def_idx].opcode;
            reginfo = opcode_reginfo[def_opcode];
            destletters = "dexy";
            for (j = 0; (letter = destletters[j]) != 0; j++) {
                dststr = strchr(reginfo, letter);
                if (dststr != NULL) {
                    break;
                }
            }
            if ((dststr == NULL)  && GET_ATTRIB(def_opcode, A_CVI_GATHER)) {
                pkt->insn[i].regno[use_regidx] = def_oreg;
                pkt->insn[i].new_value_producer_slot = pkt->insn[def_idx].slot;
            } else {
                if (dststr == NULL) {
                    /* still not there, we have a bad packet */
                    g_assert_not_reached();
                }
                g_assert(pkt->insn[def_idx].dest_idx != -1 &&
                         pkt->insn[def_idx].dest_idx == dststr - reginfo);
                int def_regnum = pkt->insn[def_idx].regno[dststr - reginfo];
                /* Now patch up the consumer with the register number */
                pkt->insn[i].regno[use_regidx] = def_regnum ^ def_oreg;
                /* special case for (Vx,Vy) */
                dststr = strchr(reginfo, 'y');
                if (def_oreg && strchr(reginfo, 'x') && dststr) {
                    def_regnum = pkt->insn[def_idx].regno[dststr - reginfo];
                    pkt->insn[i].regno[use_regidx] = def_regnum;
                }
                /*
                 * We need to remember who produces this value to later
                 * check if it was dynamically cancelled
                 */
                pkt->insn[i].new_value_producer_slot = pkt->insn[def_idx].slot;
            }
        }
    }
}

/*
 * We don't want to reorder slot1/slot0 with respect to each other.
 * So in our shuffling, we don't want to move the .cur / .tmp vmem earlier
 * Instead, we should move the producing instruction later
 * But the producing instruction might feed a .new store!
 * So we may need to move that even later.
 */

static void
decode_mmvec_move_cvi_to_end(Packet *pkt, int max)
{
    int i;
    for (i = 0; i < max; i++) {
        if (GET_ATTRIB(pkt->insn[i].opcode, A_CVI)) {
            int last_inst = pkt->num_insns - 1;
            uint16_t last_opcode = pkt->insn[last_inst].opcode;

            /*
             * If the last instruction is an endloop, move to the one before it
             * Keep endloop as the last thing always
             */
            if ((last_opcode == J2_endloop0) ||
                (last_opcode == J2_endloop1) ||
                (last_opcode == J2_endloop01)) {
                last_inst--;
            }

            decode_send_insn_to(pkt, i, last_inst);
            max--;
            i--;    /* Retry this index now that packet has rotated */
        }
    }
}

static void
decode_shuffle_for_execution_vops(Packet *pkt)
{
    /*
     * Sort for .new
     */
    int i;
    for (i = 0; i < pkt->num_insns; i++) {
        uint16_t opcode = pkt->insn[i].opcode;
        if ((GET_ATTRIB(opcode, A_LOAD) &&
             GET_ATTRIB(opcode, A_CVI_NEW)) ||
            GET_ATTRIB(opcode, A_CVI_TMP)) {
            /*
             * Find prior consuming vector instructions
             * Move to end of packet
             */
            decode_mmvec_move_cvi_to_end(pkt, i);
            break;
        }
    }

    /* Move HVX new value stores to the end of the packet */
    for (i = 0; i < pkt->num_insns - 1; i++) {
        uint16_t opcode = pkt->insn[i].opcode;
        if (GET_ATTRIB(opcode, A_STORE) &&
            GET_ATTRIB(opcode, A_CVI_NEW) &&
            !GET_ATTRIB(opcode, A_CVI_SCATTER_RELEASE)) {
            int last_inst = pkt->num_insns - 1;
            uint16_t last_opcode = pkt->insn[last_inst].opcode;

            /*
             * If the last instruction is an endloop, move to the one before it
             * Keep endloop as the last thing always
             */
            if ((last_opcode == J2_endloop0) ||
                (last_opcode == J2_endloop1) ||
                (last_opcode == J2_endloop01)) {
                last_inst--;
            }

            decode_send_insn_to(pkt, i, last_inst);
            break;
        }
    }
}

static void
check_for_vhist(Packet *pkt)
{
    pkt->vhist_insn = NULL;
    for (int i = 0; i < pkt->num_insns; i++) {
        Insn *insn = &pkt->insn[i];
        int opcode = insn->opcode;
        if (GET_ATTRIB(opcode, A_CVI) && GET_ATTRIB(opcode, A_CVI_4SLOT)) {
                pkt->vhist_insn = insn;
                return;
        }
    }
}

/*
 * Public Functions
 */

SlotMask mmvec_ext_decode_find_iclass_slots(int opcode)
{
    if (GET_ATTRIB(opcode, A_CVI_VM)) {
        /* HVX memory instruction */
        if (GET_ATTRIB(opcode, A_RESTRICT_SLOT0ONLY)) {
            return SLOTS_0;
        } else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT1ONLY)) {
            return SLOTS_1;
        }
        return SLOTS_01;
    } else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT2ONLY)) {
        return SLOTS_2;
    } else if (GET_ATTRIB(opcode, A_CVI_VX)) {
        /* HVX multiply instruction */
        return SLOTS_23;
    } else if (GET_ATTRIB(opcode, A_CVI_VS_VX)) {
        /* HVX permute/shift instruction */
        return SLOTS_23;
    } else {
        return SLOTS_0123;
    }
}

void mmvec_ext_decode_checks(Packet *pkt, bool disas_only)
{
    check_new_value(pkt);
    if (!disas_only) {
        decode_shuffle_for_execution_vops(pkt);
    }
    check_for_vhist(pkt);
}
