/*
 * 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(int mode)
{
    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_single_env, "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(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(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 do_interrupt(CPUUniCore32State *env)
{
    uint32_t addr;
    int new_mode;

    switch (env->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(env, "Unhandled exception 0x%x\n", env->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;
    env->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)
{
    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(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(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(env, "wrong page type!");
        }
        break;
    default:
        cpu_abort(env, "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(CPUUniCore32State *env, target_ulong address,
                              int access_type, int mmu_idx)
{
    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 %x, "
                        "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(env, address, phys_addr, prot, mmu_idx, page_size);
        return 0;
    }

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

target_phys_addr_t cpu_get_phys_page_debug(CPUUniCore32State *env,
        target_ulong addr)
{
    cpu_abort(env, "%s not supported yet\n", __func__);
    return addr;
}
