/*
 *  CRIS helper routines.
 *
 *  Copyright (c) 2007 AXIS Communications AB
 *  Written by Edgar E. Iglesias.
 *
 * 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 "cpu.h"
#include "mmu.h"
#include "host-utils.h"


//#define CRIS_HELPER_DEBUG


#ifdef CRIS_HELPER_DEBUG
#define D(x) x
#define D_LOG(...) qemu_log(__VA__ARGS__)
#else
#define D(x)
#define D_LOG(...) do { } while (0)
#endif

#if defined(CONFIG_USER_ONLY)

void do_interrupt (CPUCRISState *env)
{
	env->exception_index = -1;
	env->pregs[PR_ERP] = env->pc;
}

int cpu_cris_handle_mmu_fault(CPUCRISState * env, target_ulong address, int rw,
                              int mmu_idx)
{
	env->exception_index = 0xaa;
	env->pregs[PR_EDA] = address;
	cpu_dump_state(env, stderr, fprintf, 0);
	return 1;
}

#else /* !CONFIG_USER_ONLY */


static void cris_shift_ccs(CPUCRISState *env)
{
	uint32_t ccs;
	/* Apply the ccs shift.  */
	ccs = env->pregs[PR_CCS];
	ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
	env->pregs[PR_CCS] = ccs;
}

int cpu_cris_handle_mmu_fault (CPUCRISState *env, target_ulong address, int rw,
                               int mmu_idx)
{
	struct cris_mmu_result res;
	int prot, miss;
	int r = -1;
	target_ulong phy;

	D(printf ("%s addr=%x pc=%x rw=%x\n", __func__, address, env->pc, rw));
	miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
				  rw, mmu_idx, 0);
	if (miss)
	{
		if (env->exception_index == EXCP_BUSFAULT)
			cpu_abort(env,
				  "CRIS: Illegal recursive bus fault."
				 "addr=%x rw=%d\n",
				 address, rw);

		env->pregs[PR_EDA] = address;
		env->exception_index = EXCP_BUSFAULT;
		env->fault_vector = res.bf_vec;
		r = 1;
	}
	else
	{
		/*
		 * Mask off the cache selection bit. The ETRAX busses do not
		 * see the top bit.
		 */
		phy = res.phy & ~0x80000000;
		prot = res.prot;
		tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
                             prot, mmu_idx, TARGET_PAGE_SIZE);
                r = 0;
	}
	if (r > 0)
            D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
                  __func__, r, env->interrupt_request, address, res.phy,
                  res.bf_vec, env->pc);
	return r;
}

static void do_interruptv10(CPUCRISState *env)
{
	int ex_vec = -1;

	D_LOG( "exception index=%d interrupt_req=%d\n",
		   env->exception_index,
		   env->interrupt_request);

	assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
	switch (env->exception_index)
	{
		case EXCP_BREAK:
			/* These exceptions are genereated by the core itself.
			   ERP should point to the insn following the brk.  */
			ex_vec = env->trap_vector;
			env->pregs[PRV10_BRP] = env->pc;
			break;

		case EXCP_NMI:
			/* NMI is hardwired to vector zero.  */
			ex_vec = 0;
			env->pregs[PR_CCS] &= ~M_FLAG_V10;
			env->pregs[PRV10_BRP] = env->pc;
			break;

		case EXCP_BUSFAULT:
                        cpu_abort(env, "Unhandled busfault");
			break;

		default:
			/* The interrupt controller gives us the vector.  */
			ex_vec = env->interrupt_vector;
			/* Normal interrupts are taken between
			   TB's.  env->pc is valid here.  */
			env->pregs[PR_ERP] = env->pc;
			break;
	}

	if (env->pregs[PR_CCS] & U_FLAG) {
		/* Swap stack pointers.  */
		env->pregs[PR_USP] = env->regs[R_SP];
		env->regs[R_SP] = env->ksp;
	}

	/* Now that we are in kernel mode, load the handlers address.  */
        env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
	env->locked_irq = 1;
	env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */

	qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
		      __func__, env->pc, ex_vec, 
		      env->pregs[PR_CCS],
		      env->pregs[PR_PID], 
		      env->pregs[PR_ERP]);
}

void do_interrupt(CPUCRISState *env)
{
	int ex_vec = -1;

	if (env->pregs[PR_VR] < 32)
		return do_interruptv10(env);

	D_LOG( "exception index=%d interrupt_req=%d\n",
		   env->exception_index,
		   env->interrupt_request);

	switch (env->exception_index)
	{
		case EXCP_BREAK:
			/* These exceptions are genereated by the core itself.
			   ERP should point to the insn following the brk.  */
			ex_vec = env->trap_vector;
			env->pregs[PR_ERP] = env->pc;
			break;

		case EXCP_NMI:
			/* NMI is hardwired to vector zero.  */
			ex_vec = 0;
			env->pregs[PR_CCS] &= ~M_FLAG_V32;
			env->pregs[PR_NRP] = env->pc;
			break;

		case EXCP_BUSFAULT:
			ex_vec = env->fault_vector;
			env->pregs[PR_ERP] = env->pc;
			break;

		default:
			/* The interrupt controller gives us the vector.  */
			ex_vec = env->interrupt_vector;
			/* Normal interrupts are taken between
			   TB's.  env->pc is valid here.  */
			env->pregs[PR_ERP] = env->pc;
			break;
	}

	/* Fill in the IDX field.  */
	env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;

	if (env->dslot) {
		D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
			  " ERP=%x pid=%x ccs=%x cc=%d %x\n",
			  ex_vec, env->pc, env->dslot,
			  env->regs[R_SP],
			  env->pregs[PR_ERP], env->pregs[PR_PID],
			  env->pregs[PR_CCS],
			  env->cc_op, env->cc_mask);
		/* We loose the btarget, btaken state here so rexec the
		   branch.  */
		env->pregs[PR_ERP] -= env->dslot;
		/* Exception starts with dslot cleared.  */
		env->dslot = 0;
	}
	
	if (env->pregs[PR_CCS] & U_FLAG) {
		/* Swap stack pointers.  */
		env->pregs[PR_USP] = env->regs[R_SP];
		env->regs[R_SP] = env->ksp;
	}

	/* Apply the CRIS CCS shift. Clears U if set.  */
	cris_shift_ccs(env);

	/* Now that we are in kernel mode, load the handlers address.
	   This load may not fault, real hw leaves that behaviour as
	   undefined.  */
        env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);

	/* Clear the excption_index to avoid spurios hw_aborts for recursive
	   bus faults.  */
	env->exception_index = -1;

	D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
		   __func__, env->pc, ex_vec,
		   env->pregs[PR_CCS],
		   env->pregs[PR_PID], 
		   env->pregs[PR_ERP]);
}

target_phys_addr_t cpu_get_phys_page_debug(CPUCRISState * env, target_ulong addr)
{
	uint32_t phy = addr;
	struct cris_mmu_result res;
	int miss;

	miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
	/* If D TLB misses, try I TLB.  */
	if (miss) {
		miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
	}

	if (!miss)
		phy = res.phy;
	D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
	return phy;
}
#endif
