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