File:  [Qemu by Fabrice Bellard] / qemu / target-cris / helper.c
Revision 1.1.1.8 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:31:57 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, HEAD
qemu 1.0.1

    1: /*
    2:  *  CRIS helper routines.
    3:  *
    4:  *  Copyright (c) 2007 AXIS Communications AB
    5:  *  Written by Edgar E. Iglesias.
    6:  *
    7:  * This library is free software; you can redistribute it and/or
    8:  * modify it under the terms of the GNU Lesser General Public
    9:  * License as published by the Free Software Foundation; either
   10:  * version 2 of the License, or (at your option) any later version.
   11:  *
   12:  * This library is distributed in the hope that it will be useful,
   13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15:  * Lesser General Public License for more details.
   16:  *
   17:  * You should have received a copy of the GNU Lesser General Public
   18:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
   19:  */
   20: 
   21: #include <stdio.h>
   22: #include <string.h>
   23: 
   24: #include "config.h"
   25: #include "cpu.h"
   26: #include "mmu.h"
   27: #include "host-utils.h"
   28: 
   29: 
   30: //#define CRIS_HELPER_DEBUG
   31: 
   32: 
   33: #ifdef CRIS_HELPER_DEBUG
   34: #define D(x) x
   35: #define D_LOG(...) qemu_log(__VA__ARGS__)
   36: #else
   37: #define D(x)
   38: #define D_LOG(...) do { } while (0)
   39: #endif
   40: 
   41: #if defined(CONFIG_USER_ONLY)
   42: 
   43: void do_interrupt (CPUState *env)
   44: {
   45: 	env->exception_index = -1;
   46: 	env->pregs[PR_ERP] = env->pc;
   47: }
   48: 
   49: int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
   50:                               int mmu_idx)
   51: {
   52: 	env->exception_index = 0xaa;
   53: 	env->pregs[PR_EDA] = address;
   54: 	cpu_dump_state(env, stderr, fprintf, 0);
   55: 	return 1;
   56: }
   57: 
   58: #else /* !CONFIG_USER_ONLY */
   59: 
   60: 
   61: static void cris_shift_ccs(CPUState *env)
   62: {
   63: 	uint32_t ccs;
   64: 	/* Apply the ccs shift.  */
   65: 	ccs = env->pregs[PR_CCS];
   66: 	ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
   67: 	env->pregs[PR_CCS] = ccs;
   68: }
   69: 
   70: int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
   71:                                int mmu_idx)
   72: {
   73: 	struct cris_mmu_result res;
   74: 	int prot, miss;
   75: 	int r = -1;
   76: 	target_ulong phy;
   77: 
   78: 	D(printf ("%s addr=%x pc=%x rw=%x\n", __func__, address, env->pc, rw));
   79: 	miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
   80: 				  rw, mmu_idx, 0);
   81: 	if (miss)
   82: 	{
   83: 		if (env->exception_index == EXCP_BUSFAULT)
   84: 			cpu_abort(env,
   85: 				  "CRIS: Illegal recursive bus fault."
   86: 				 "addr=%x rw=%d\n",
   87: 				 address, rw);
   88: 
   89: 		env->pregs[PR_EDA] = address;
   90: 		env->exception_index = EXCP_BUSFAULT;
   91: 		env->fault_vector = res.bf_vec;
   92: 		r = 1;
   93: 	}
   94: 	else
   95: 	{
   96: 		/*
   97: 		 * Mask off the cache selection bit. The ETRAX busses do not
   98: 		 * see the top bit.
   99: 		 */
  100: 		phy = res.phy & ~0x80000000;
  101: 		prot = res.prot;
  102: 		tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
  103:                              prot, mmu_idx, TARGET_PAGE_SIZE);
  104:                 r = 0;
  105: 	}
  106: 	if (r > 0)
  107:             D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
  108:                   __func__, r, env->interrupt_request, address, res.phy,
  109:                   res.bf_vec, env->pc);
  110: 	return r;
  111: }
  112: 
  113: static void do_interruptv10(CPUState *env)
  114: {
  115: 	int ex_vec = -1;
  116: 
  117: 	D_LOG( "exception index=%d interrupt_req=%d\n",
  118: 		   env->exception_index,
  119: 		   env->interrupt_request);
  120: 
  121: 	assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
  122: 	switch (env->exception_index)
  123: 	{
  124: 		case EXCP_BREAK:
  125: 			/* These exceptions are genereated by the core itself.
  126: 			   ERP should point to the insn following the brk.  */
  127: 			ex_vec = env->trap_vector;
  128: 			env->pregs[PR_ERP] = env->pc;
  129: 			break;
  130: 
  131: 		case EXCP_NMI:
  132: 			/* NMI is hardwired to vector zero.  */
  133: 			ex_vec = 0;
  134: 			env->pregs[PR_CCS] &= ~M_FLAG;
  135: 			env->pregs[PR_NRP] = env->pc;
  136: 			break;
  137: 
  138: 		case EXCP_BUSFAULT:
  139:                         cpu_abort(env, "Unhandled busfault");
  140: 			break;
  141: 
  142: 		default:
  143: 			/* The interrupt controller gives us the vector.  */
  144: 			ex_vec = env->interrupt_vector;
  145: 			/* Normal interrupts are taken between
  146: 			   TB's.  env->pc is valid here.  */
  147: 			env->pregs[PR_ERP] = env->pc;
  148: 			break;
  149: 	}
  150: 
  151: 	if (env->pregs[PR_CCS] & U_FLAG) {
  152: 		/* Swap stack pointers.  */
  153: 		env->pregs[PR_USP] = env->regs[R_SP];
  154: 		env->regs[R_SP] = env->ksp;
  155: 	}
  156: 
  157: 	/* Now that we are in kernel mode, load the handlers address.  */
  158: 	env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
  159: 	env->locked_irq = 1;
  160: 	env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
  161: 
  162: 	qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
  163: 		      __func__, env->pc, ex_vec, 
  164: 		      env->pregs[PR_CCS],
  165: 		      env->pregs[PR_PID], 
  166: 		      env->pregs[PR_ERP]);
  167: }
  168: 
  169: void do_interrupt(CPUState *env)
  170: {
  171: 	int ex_vec = -1;
  172: 
  173: 	if (env->pregs[PR_VR] < 32)
  174: 		return do_interruptv10(env);
  175: 
  176: 	D_LOG( "exception index=%d interrupt_req=%d\n",
  177: 		   env->exception_index,
  178: 		   env->interrupt_request);
  179: 
  180: 	switch (env->exception_index)
  181: 	{
  182: 		case EXCP_BREAK:
  183: 			/* These exceptions are genereated by the core itself.
  184: 			   ERP should point to the insn following the brk.  */
  185: 			ex_vec = env->trap_vector;
  186: 			env->pregs[PR_ERP] = env->pc;
  187: 			break;
  188: 
  189: 		case EXCP_NMI:
  190: 			/* NMI is hardwired to vector zero.  */
  191: 			ex_vec = 0;
  192: 			env->pregs[PR_CCS] &= ~M_FLAG;
  193: 			env->pregs[PR_NRP] = env->pc;
  194: 			break;
  195: 
  196: 		case EXCP_BUSFAULT:
  197: 			ex_vec = env->fault_vector;
  198: 			env->pregs[PR_ERP] = env->pc;
  199: 			break;
  200: 
  201: 		default:
  202: 			/* The interrupt controller gives us the vector.  */
  203: 			ex_vec = env->interrupt_vector;
  204: 			/* Normal interrupts are taken between
  205: 			   TB's.  env->pc is valid here.  */
  206: 			env->pregs[PR_ERP] = env->pc;
  207: 			break;
  208: 	}
  209: 
  210: 	/* Fill in the IDX field.  */
  211: 	env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
  212: 
  213: 	if (env->dslot) {
  214: 		D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
  215: 			  " ERP=%x pid=%x ccs=%x cc=%d %x\n",
  216: 			  ex_vec, env->pc, env->dslot,
  217: 			  env->regs[R_SP],
  218: 			  env->pregs[PR_ERP], env->pregs[PR_PID],
  219: 			  env->pregs[PR_CCS],
  220: 			  env->cc_op, env->cc_mask);
  221: 		/* We loose the btarget, btaken state here so rexec the
  222: 		   branch.  */
  223: 		env->pregs[PR_ERP] -= env->dslot;
  224: 		/* Exception starts with dslot cleared.  */
  225: 		env->dslot = 0;
  226: 	}
  227: 	
  228: 	if (env->pregs[PR_CCS] & U_FLAG) {
  229: 		/* Swap stack pointers.  */
  230: 		env->pregs[PR_USP] = env->regs[R_SP];
  231: 		env->regs[R_SP] = env->ksp;
  232: 	}
  233: 
  234: 	/* Apply the CRIS CCS shift. Clears U if set.  */
  235: 	cris_shift_ccs(env);
  236: 
  237: 	/* Now that we are in kernel mode, load the handlers address.
  238: 	   This load may not fault, real hw leaves that behaviour as
  239: 	   undefined.  */
  240: 	env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
  241: 
  242: 	/* Clear the excption_index to avoid spurios hw_aborts for recursive
  243: 	   bus faults.  */
  244: 	env->exception_index = -1;
  245: 
  246: 	D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
  247: 		   __func__, env->pc, ex_vec,
  248: 		   env->pregs[PR_CCS],
  249: 		   env->pregs[PR_PID], 
  250: 		   env->pregs[PR_ERP]);
  251: }
  252: 
  253: target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
  254: {
  255: 	uint32_t phy = addr;
  256: 	struct cris_mmu_result res;
  257: 	int miss;
  258: 
  259: 	miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
  260: 	/* If D TLB misses, try I TLB.  */
  261: 	if (miss) {
  262: 		miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
  263: 	}
  264: 
  265: 	if (!miss)
  266: 		phy = res.phy;
  267: 	D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
  268: 	return phy;
  269: }
  270: #endif

unix.superglobalmegacorp.com