/*
 * Softmmu related functions
 *
 * Copyright (C) 2010-2012 Guan Xuetao
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation, or any later version.
 * See the COPYING file in the top-level directory.
 */
#ifdef CONFIG_USER_ONLY
#error This file only exist under softmmu circumstance
#endif

#include <cpu.h>

#undef DEBUG_UC32

#ifdef DEBUG_UC32
#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__)
#else
#define DPRINTF(fmt, ...) do {} while (0)
#endif

#define SUPERPAGE_SIZE             (1 << 22)
#define UC32_PAGETABLE_READ        (1 << 8)
#define UC32_PAGETABLE_WRITE       (1 << 7)
#define UC32_PAGETABLE_EXEC        (1 << 6)
#define UC32_PAGETABLE_EXIST       (1 << 2)
#define PAGETABLE_TYPE(x)          ((x) & 3)


/* Map CPU modes onto saved register banks.  */
static inline int bank_number(CPUUniCore32State *env, int mode)
{
    UniCore32CPU *cpu = uc32_env_get_cpu(env);

    switch (mode) {
    case ASR_MODE_USER:
    case ASR_MODE_SUSR:
        return 0;
    case ASR_MODE_PRIV:
        return 1;
    case ASR_MODE_TRAP:
        return 2;
    case ASR_MODE_EXTN:
        return 3;
    case ASR_MODE_INTR:
        return 4;
    }
    cpu_abort(CPU(cpu), "Bad mode %x\n", mode);
    return -1;
}

void switch_mode(CPUUniCore32State *env, int mode)
{
    int old_mode;
    int i;

    old_mode = env->uncached_asr & ASR_M;
    if (mode == old_mode) {
        return;
    }

    i = bank_number(env, old_mode);
    env->banked_r29[i] = env->regs[29];
    env->banked_r30[i] = env->regs[30];
    env->banked_bsr[i] = env->bsr;

    i = bank_number(env, mode);
    env->regs[29] = env->banked_r29[i];
    env->regs[30] = env->banked_r30[i];
    env->bsr = env->banked_bsr[i];
}

/* Handle a CPU exception.  */
void uc32_cpu_do_interrupt(CPUState *cs)
{
    UniCore32CPU *cpu = UNICORE32_CPU(cs);
    CPUUniCore32State *env = &cpu->env;
    uint32_t addr;
    int new_mode;

    switch (cs->exception_index) {
    case UC32_EXCP_PRIV:
        new_mode = ASR_MODE_PRIV;
        addr = 0x08;
        break;
    case UC32_EXCP_ITRAP:
        DPRINTF("itrap happened at %x\n", env->regs[31]);
        new_mode = ASR_MODE_TRAP;
        addr = 0x0c;
        break;
    case UC32_EXCP_DTRAP:
        DPRINTF("dtrap happened at %x\n", env->regs[31]);
        new_mode = ASR_MODE_TRAP;
        addr = 0x10;
        break;
    case UC32_EXCP_INTR:
        new_mode = ASR_MODE_INTR;
        addr = 0x18;
        break;
    default:
        cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
        return;
    }
    /* High vectors.  */
    if (env->cp0.c1_sys & (1 << 13)) {
        addr += 0xffff0000;
    }

    switch_mode(env, new_mode);
    env->bsr = cpu_asr_read(env);
    env->uncached_asr = (env->uncached_asr & ~ASR_M) | new_mode;
    env->uncached_asr |= ASR_I;
    /* The PC already points to the proper instruction.  */
    env->regs[30] = env->regs[31];
    env->regs[31] = addr;
    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}

static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address,
        int access_type, int is_user, uint32_t *phys_ptr, int *prot,
        target_ulong *page_size)
{
    UniCore32CPU *cpu = uc32_env_get_cpu(env);
    CPUState *cs = CPU(cpu);
    int code;
    uint32_t table;
    uint32_t desc;
    uint32_t phys_addr;

    /* Pagetable walk.  */
    /* Lookup l1 descriptor.  */
    table = env->cp0.c2_base & 0xfffff000;
    table |= (address >> 20) & 0xffc;
    desc = ldl_phys(cs->as, table);
    code = 0;
    switch (PAGETABLE_TYPE(desc)) {
    case 3:
        /* Superpage  */
        if (!(desc & UC32_PAGETABLE_EXIST)) {
            code = 0x0b; /* superpage miss */
            goto do_fault;
        }
        phys_addr = (desc & 0xffc00000) | (address & 0x003fffff);
        *page_size = SUPERPAGE_SIZE;
        break;
    case 0:
        /* Lookup l2 entry.  */
        if (is_user) {
            DPRINTF("PGD address %x, desc %x\n", table, desc);
        }
        if (!(desc & UC32_PAGETABLE_EXIST)) {
            code = 0x05; /* second pagetable miss */
            goto do_fault;
        }
        table = (desc & 0xfffff000) | ((address >> 10) & 0xffc);
        desc = ldl_phys(cs->as, table);
        /* 4k page.  */
        if (is_user) {
            DPRINTF("PTE address %x, desc %x\n", table, desc);
        }
        if (!(desc & UC32_PAGETABLE_EXIST)) {
            code = 0x08; /* page miss */
            goto do_fault;
        }
        switch (PAGETABLE_TYPE(desc)) {
        case 0:
            phys_addr = (desc & 0xfffff000) | (address & 0xfff);
            *page_size = TARGET_PAGE_SIZE;
            break;
        default:
            cpu_abort(CPU(cpu), "wrong page type!");
        }
        break;
    default:
        cpu_abort(CPU(cpu), "wrong page type!");
    }

    *phys_ptr = phys_addr;
    *prot = 0;
    /* Check access permissions.  */
    if (desc & UC32_PAGETABLE_READ) {
        *prot |= PAGE_READ;
    } else {
        if (is_user && (access_type == 0)) {
            code = 0x11; /* access unreadable area */
            goto do_fault;
        }
    }

    if (desc & UC32_PAGETABLE_WRITE) {
        *prot |= PAGE_WRITE;
    } else {
        if (is_user && (access_type == 1)) {
            code = 0x12; /* access unwritable area */
            goto do_fault;
        }
    }

    if (desc & UC32_PAGETABLE_EXEC) {
        *prot |= PAGE_EXEC;
    } else {
        if (is_user && (access_type == 2)) {
            code = 0x13; /* access unexecutable area */
            goto do_fault;
        }
    }

do_fault:
    return code;
}

int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
                              int access_type, int mmu_idx)
{
    UniCore32CPU *cpu = UNICORE32_CPU(cs);
    CPUUniCore32State *env = &cpu->env;
    uint32_t phys_addr;
    target_ulong page_size;
    int prot;
    int ret, is_user;

    ret = 1;
    is_user = mmu_idx == MMU_USER_IDX;

    if ((env->cp0.c1_sys & 1) == 0) {
        /* MMU disabled.  */
        phys_addr = address;
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
        page_size = TARGET_PAGE_SIZE;
        ret = 0;
    } else {
        if ((address & (1 << 31)) || (is_user)) {
            ret = get_phys_addr_ucv2(env, address, access_type, is_user,
                                    &phys_addr, &prot, &page_size);
            if (is_user) {
                DPRINTF("user space access: ret %x, address %" VADDR_PRIx ", "
                        "access_type %x, phys_addr %x, prot %x\n",
                        ret, address, access_type, phys_addr, prot);
            }
        } else {
            /*IO memory */
            phys_addr = address | (1 << 31);
            prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
            page_size = TARGET_PAGE_SIZE;
            ret = 0;
        }
    }

    if (ret == 0) {
        /* Map a single page.  */
        phys_addr &= TARGET_PAGE_MASK;
        address &= TARGET_PAGE_MASK;
        tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size);
        return 0;
    }

    env->cp0.c3_faultstatus = ret;
    env->cp0.c4_faultaddr = address;
    if (access_type == 2) {
        cs->exception_index = UC32_EXCP_ITRAP;
    } else {
        cs->exception_index = UC32_EXCP_DTRAP;
    }
    return ret;
}

hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
    UniCore32CPU *cpu = UNICORE32_CPU(cs);

    cpu_abort(CPU(cpu), "%s not supported yet\n", __func__);
    return addr;
}
