/*
 * Copyright (c) 2017, Max Filippov, Open Source and Linux Lab.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Open Source and Linux Lab nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "qemu/osdep.h"
#include "disas/bfd.h"
#include "hw/xtensa/xtensa-isa.h"

int print_insn_xtensa(bfd_vma memaddr, struct disassemble_info *info)
{
    xtensa_isa isa = info->private_data;
    xtensa_insnbuf insnbuf = xtensa_insnbuf_alloc(isa);
    xtensa_insnbuf slotbuf = xtensa_insnbuf_alloc(isa);
    bfd_byte *buffer = g_malloc(1);
    int status = info->read_memory_func(memaddr, buffer, 1, info);
    xtensa_format fmt;
    unsigned slot, slots;
    unsigned len;

    if (status) {
        info->memory_error_func(status, memaddr, info);
        len = -1;
        goto out;
    }
    len = xtensa_isa_length_from_chars(isa, buffer);
    if (len == XTENSA_UNDEFINED) {
        info->fprintf_func(info->stream, ".byte 0x%02x", buffer[0]);
        len = 1;
        goto out;
    }
    buffer = g_realloc(buffer, len);
    status = info->read_memory_func(memaddr + 1, buffer + 1, len - 1, info);
    if (status) {
        info->fprintf_func(info->stream, ".byte 0x%02x", buffer[0]);
        info->memory_error_func(status, memaddr + 1, info);
        len = 1;
        goto out;
    }

    xtensa_insnbuf_from_chars(isa, insnbuf, buffer, len);
    fmt = xtensa_format_decode(isa, insnbuf);
    if (fmt == XTENSA_UNDEFINED) {
        unsigned i;

        for (i = 0; i < len; ++i) {
            info->fprintf_func(info->stream, "%s 0x%02x",
                               i ? ", " : ".byte ", buffer[i]);
        }
        goto out;
    }
    slots = xtensa_format_num_slots(isa, fmt);

    if (slots > 1) {
        info->fprintf_func(info->stream, "{ ");
    }

    for (slot = 0; slot < slots; ++slot) {
        xtensa_opcode opc;
        unsigned opnd, vopnd, opnds;

        if (slot) {
            info->fprintf_func(info->stream, "; ");
        }
        xtensa_format_get_slot(isa, fmt, slot, insnbuf, slotbuf);
        opc = xtensa_opcode_decode(isa, fmt, slot, slotbuf);
        if (opc == XTENSA_UNDEFINED) {
            info->fprintf_func(info->stream, "???");
            continue;
        }
        opnds = xtensa_opcode_num_operands(isa, opc);

        info->fprintf_func(info->stream, "%s", xtensa_opcode_name(isa, opc));

        for (opnd = vopnd = 0; opnd < opnds; ++opnd) {
            if (xtensa_operand_is_visible(isa, opc, opnd)) {
                uint32_t v = 0xbadc0de;
                int rc;

                info->fprintf_func(info->stream, vopnd ? ", " : "\t");
                xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
                                         slotbuf, &v);
                rc = xtensa_operand_decode(isa, opc, opnd, &v);
                if (rc == XTENSA_UNDEFINED) {
                    info->fprintf_func(info->stream, "???");
                } else if (xtensa_operand_is_register(isa, opc, opnd)) {
                    xtensa_regfile rf = xtensa_operand_regfile(isa, opc, opnd);

                    info->fprintf_func(info->stream, "%s%d",
                                       xtensa_regfile_shortname(isa, rf), v);
                } else if (xtensa_operand_is_PCrelative(isa, opc, opnd)) {
                    xtensa_operand_undo_reloc(isa, opc, opnd, &v, memaddr);
                    info->fprintf_func(info->stream, "0x%x", v);
                } else {
                    info->fprintf_func(info->stream, "%d", v);
                }
                ++vopnd;
            }
        }
    }
    if (slots > 1) {
        info->fprintf_func(info->stream, " }");
    }

out:
    g_free(buffer);
    xtensa_insnbuf_free(isa, insnbuf);
    xtensa_insnbuf_free(isa, slotbuf);

    return len;
}
