/*
 * 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)
{
    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(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(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 (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;
    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)
{
    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;
}

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