/*
 * Xtensa gdb server stub
 *
 * Copyright (c) 2003-2005 Fabrice Bellard
 * Copyright (c) 2013 SUSE LINUX Products GmbH
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "cpu.h"
#include "exec/gdbstub.h"
#include "qemu/log.h"

enum {
  xtRegisterTypeArRegfile = 1,  /* Register File ar0..arXX.  */
  xtRegisterTypeSpecialReg,     /* CPU states, such as PS, Booleans, (rsr).  */
  xtRegisterTypeUserReg,        /* User defined registers (rur).  */
  xtRegisterTypeTieRegfile,     /* User define register files.  */
  xtRegisterTypeTieState,       /* TIE States (mapped on user regs).  */
  xtRegisterTypeMapped,         /* Mapped on Special Registers.  */
  xtRegisterTypeUnmapped,       /* Special case of masked registers.  */
  xtRegisterTypeWindow,         /* Live window registers (a0..a15).  */
  xtRegisterTypeVirtual,        /* PC, FP.  */
  xtRegisterTypeUnknown
};

#define XTENSA_REGISTER_FLAGS_PRIVILEGED        0x0001
#define XTENSA_REGISTER_FLAGS_READABLE          0x0002
#define XTENSA_REGISTER_FLAGS_WRITABLE          0x0004
#define XTENSA_REGISTER_FLAGS_VOLATILE          0x0008

void xtensa_count_regs(const XtensaConfig *config,
                       unsigned *n_regs, unsigned *n_core_regs)
{
    unsigned i;
    bool count_core_regs = true;

    for (i = 0; config->gdb_regmap.reg[i].targno >= 0; ++i) {
        if (config->gdb_regmap.reg[i].type != xtRegisterTypeTieState &&
            config->gdb_regmap.reg[i].type != xtRegisterTypeMapped &&
            config->gdb_regmap.reg[i].type != xtRegisterTypeUnmapped) {
            ++*n_regs;
            if (count_core_regs) {
                if ((config->gdb_regmap.reg[i].flags &
                     XTENSA_REGISTER_FLAGS_PRIVILEGED) == 0) {
                    ++*n_core_regs;
                } else {
                    count_core_regs = false;
                }
            }
        }
    }
}

int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
{
    XtensaCPU *cpu = XTENSA_CPU(cs);
    CPUXtensaState *env = &cpu->env;
    const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
#ifdef CONFIG_USER_ONLY
    int num_regs = env->config->gdb_regmap.num_core_regs;
#else
    int num_regs = env->config->gdb_regmap.num_regs;
#endif
    unsigned i;

    if (n < 0 || n >= num_regs) {
        return 0;
    }

    switch (reg->type) {
    case xtRegisterTypeVirtual: /*pc*/
        return gdb_get_reg32(mem_buf, env->pc);

    case xtRegisterTypeArRegfile: /*ar*/
        xtensa_sync_phys_from_window(env);
        return gdb_get_reg32(mem_buf, env->phys_regs[(reg->targno & 0xff)
                                                     % env->config->nareg]);

    case xtRegisterTypeSpecialReg: /*SR*/
        return gdb_get_reg32(mem_buf, env->sregs[reg->targno & 0xff]);

    case xtRegisterTypeUserReg: /*UR*/
        return gdb_get_reg32(mem_buf, env->uregs[reg->targno & 0xff]);

    case xtRegisterTypeTieRegfile: /*f*/
        i = reg->targno & 0x0f;
        switch (reg->size) {
        case 4:
            return gdb_get_reg32(mem_buf,
                                 float32_val(env->fregs[i].f32[FP_F32_LOW]));
        case 8:
            return gdb_get_reg64(mem_buf, float64_val(env->fregs[i].f64));
        default:
            qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported size %d\n",
                          __func__, n, reg->size);
            memset(mem_buf, 0, reg->size);
            return reg->size;
        }

    case xtRegisterTypeWindow: /*a*/
        return gdb_get_reg32(mem_buf, env->regs[reg->targno & 0x0f]);

    default:
        qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported type %d\n",
                      __func__, n, reg->type);
        memset(mem_buf, 0, reg->size);
        return reg->size;
    }
}

int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
    XtensaCPU *cpu = XTENSA_CPU(cs);
    CPUXtensaState *env = &cpu->env;
    uint32_t tmp;
    const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
#ifdef CONFIG_USER_ONLY
    int num_regs = env->config->gdb_regmap.num_core_regs;
#else
    int num_regs = env->config->gdb_regmap.num_regs;
#endif

    if (n < 0 || n >= num_regs) {
        return 0;
    }

    tmp = ldl_p(mem_buf);

    switch (reg->type) {
    case xtRegisterTypeVirtual: /*pc*/
        env->pc = tmp;
        break;

    case xtRegisterTypeArRegfile: /*ar*/
        env->phys_regs[(reg->targno & 0xff) % env->config->nareg] = tmp;
        xtensa_sync_window_from_phys(env);
        break;

    case xtRegisterTypeSpecialReg: /*SR*/
        env->sregs[reg->targno & 0xff] = tmp;
        break;

    case xtRegisterTypeUserReg: /*UR*/
        env->uregs[reg->targno & 0xff] = tmp;
        break;

    case xtRegisterTypeTieRegfile: /*f*/
        switch (reg->size) {
        case 4:
            env->fregs[reg->targno & 0x0f].f32[FP_F32_LOW] = make_float32(tmp);
            return 4;
        case 8:
            env->fregs[reg->targno & 0x0f].f64 = make_float64(tmp);
            return 8;
        default:
            qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported size %d\n",
                          __func__, n, reg->size);
            return reg->size;
        }

    case xtRegisterTypeWindow: /*a*/
        env->regs[reg->targno & 0x0f] = tmp;
        break;

    default:
        qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported type %d\n",
                      __func__, n, reg->type);
        return reg->size;
    }

    return 4;
}
