/*
 * LOONGARCH gdb server stub
 *
 * Copyright (c) 2021 Loongson Technology Corporation Limited
 *
 * SPDX-License-Identifier: LGPL-2.1+
 */

#include "qemu/osdep.h"
#include "cpu.h"
#include "internals.h"
#include "exec/gdbstub.h"
#include "gdbstub/helpers.h"
#include "vec.h"

uint64_t read_fcc(CPULoongArchState *env)
{
    uint64_t ret = 0;

    for (int i = 0; i < 8; ++i) {
        ret |= (uint64_t)env->cf[i] << (i * 8);
    }

    return ret;
}

void write_fcc(CPULoongArchState *env, uint64_t val)
{
    for (int i = 0; i < 8; ++i) {
        env->cf[i] = (val >> (i * 8)) & 1;
    }
}

int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
    CPULoongArchState *env = cpu_env(cs);
    uint64_t val;

    if (0 <= n && n < 32) {
        val = env->gpr[n];
    } else if (n == 32) {
        /* orig_a0 */
        val = 0;
    } else if (n == 33) {
        val = env->pc;
    } else if (n == 34) {
        val = env->CSR_BADV;
    }

    if (0 <= n && n <= 34) {
        if (is_la64(env)) {
            return gdb_get_reg64(mem_buf, val);
        } else {
            return gdb_get_reg32(mem_buf, val);
        }
    }
    return 0;
}

int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
    CPULoongArchState *env = cpu_env(cs);
    target_ulong tmp;
    int read_length;
    int length = 0;

    if (is_la64(env)) {
        tmp = ldq_p(mem_buf);
        read_length = 8;
    } else {
        tmp = ldl_p(mem_buf);
        read_length = 4;
    }

    if (0 <= n && n < 32) {
        env->gpr[n] = tmp;
        length = read_length;
    } else if (n == 33) {
        set_pc(env, tmp);
        length = read_length;
    }
    return length;
}

static int loongarch_gdb_get_fpu(CPUState *cs, GByteArray *mem_buf, int n)
{
    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
    CPULoongArchState *env = &cpu->env;

    if (0 <= n && n < 32) {
        return gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(0));
    } else if (32 <= n && n < 40) {
        return gdb_get_reg8(mem_buf, env->cf[n - 32]);
    } else if (n == 40) {
        return gdb_get_reg32(mem_buf, env->fcsr0);
    }
    return 0;
}

static int loongarch_gdb_set_fpu(CPUState *cs, uint8_t *mem_buf, int n)
{
    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
    CPULoongArchState *env = &cpu->env;
    int length = 0;

    if (0 <= n && n < 32) {
        env->fpr[n].vreg.D(0) = ldq_p(mem_buf);
        length = 8;
    } else if (32 <= n && n < 40) {
        env->cf[n - 32] = ldub_p(mem_buf);
        length = 1;
    } else if (n == 40) {
        env->fcsr0 = ldl_p(mem_buf);
        length = 4;
    }
    return length;
}

#define VREG_NUM       32
#define REG64_LEN      64

static int loongarch_gdb_get_vec(CPUState *cs, GByteArray *mem_buf, int n, int vl)
{
    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
    CPULoongArchState *env = &cpu->env;
    int i, length = 0;

    if (0 <= n && n < VREG_NUM) {
        for (i = 0; i < vl / REG64_LEN; i++) {
            length += gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(i));
        }
    }

    return length;
}

static int loongarch_gdb_set_vec(CPUState *cs, uint8_t *mem_buf, int n, int vl)
{
    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
    CPULoongArchState *env = &cpu->env;
    int i, length = 0;

    if (0 <= n && n < VREG_NUM) {
        for (i = 0; i < vl / REG64_LEN; i++) {
            env->fpr[n].vreg.D(i) = ldq_le_p(mem_buf + 8 * i);
            length += 8;
        }
    }

    return length;
}

static int loongarch_gdb_get_lsx(CPUState *cs, GByteArray *mem_buf, int n)
{
    return loongarch_gdb_get_vec(cs, mem_buf, n, LSX_LEN);
}

static int loongarch_gdb_set_lsx(CPUState *cs, uint8_t *mem_buf, int n)
{
    return loongarch_gdb_set_vec(cs, mem_buf, n, LSX_LEN);
}

static int loongarch_gdb_get_lasx(CPUState *cs, GByteArray *mem_buf, int n)
{
    return loongarch_gdb_get_vec(cs, mem_buf, n, LASX_LEN);
}

static int loongarch_gdb_set_lasx(CPUState *cs, uint8_t *mem_buf, int n)
{
    return loongarch_gdb_set_vec(cs, mem_buf, n, LASX_LEN);
}

void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs)
{
    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
    CPULoongArchState *env = &cpu->env;

    if (FIELD_EX32(env->cpucfg[2], CPUCFG2, FP)) {
        gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu,
                                 gdb_find_static_feature("loongarch-fpu.xml"), 0);
    }

    if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LSX)) {
        gdb_register_coprocessor(cs, loongarch_gdb_get_lsx, loongarch_gdb_set_lsx,
                                 gdb_find_static_feature("loongarch-lsx.xml"), 0);
    }

    if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LASX)) {
        gdb_register_coprocessor(cs, loongarch_gdb_get_lasx, loongarch_gdb_set_lasx,
                                 gdb_find_static_feature("loongarch-lasx.xml"), 0);
    }
}
