sh4/r2d: update pci, usb and kernel management
[qemu/sh4.git] / target-cris / op_helper.c
bloba681f84f35dca594663f6dc247e191d23dfb0319
1 /*
2 * CRIS helper routines
4 * Copyright (c) 2007 AXIS Communications
5 * Written by Edgar E. Iglesias
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.
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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <assert.h>
23 #include "exec.h"
24 #include "mmu.h"
25 #include "helper.h"
27 #define D(x)
29 #if !defined(CONFIG_USER_ONLY)
31 #define MMUSUFFIX _mmu
33 #define SHIFT 0
34 #include "softmmu_template.h"
36 #define SHIFT 1
37 #include "softmmu_template.h"
39 #define SHIFT 2
40 #include "softmmu_template.h"
42 #define SHIFT 3
43 #include "softmmu_template.h"
45 /* Try to fill the TLB and return an exception if error. If retaddr is
46 NULL, it means that the function was called in C code (i.e. not
47 from generated code or from helper.c) */
48 /* XXX: fix it to restore all registers */
49 void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
51 TranslationBlock *tb;
52 CPUState *saved_env;
53 unsigned long pc;
54 int ret;
56 /* XXX: hack to restore env in all cases, even if not called from
57 generated code */
58 saved_env = env;
59 env = cpu_single_env;
61 D(fprintf(logfile, "%s pc=%x tpc=%x ra=%x\n", __func__,
62 env->pc, env->debug1, retaddr));
63 ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
64 if (unlikely(ret)) {
65 if (retaddr) {
66 /* now we have a real cpu fault */
67 pc = (unsigned long)retaddr;
68 tb = tb_find_pc(pc);
69 if (tb) {
70 /* the PC is inside the translated code. It means that we have
71 a virtual CPU fault */
72 cpu_restore_state(tb, env, pc, NULL);
74 /* Evaluate flags after retranslation. */
75 helper_top_evaluate_flags();
78 cpu_loop_exit();
80 env = saved_env;
83 #endif
85 void helper_raise_exception(uint32_t index)
87 env->exception_index = index;
88 cpu_loop_exit();
91 void helper_tlb_flush_pid(uint32_t pid)
93 #if !defined(CONFIG_USER_ONLY)
94 pid &= 0xff;
95 if (pid != (env->pregs[PR_PID] & 0xff))
96 cris_mmu_flush_pid(env, env->pregs[PR_PID]);
97 #endif
100 void helper_spc_write(uint32_t new_spc)
102 #if !defined(CONFIG_USER_ONLY)
103 tlb_flush_page(env, env->pregs[PR_SPC]);
104 tlb_flush_page(env, new_spc);
105 #endif
108 void helper_dump(uint32_t a0, uint32_t a1, uint32_t a2)
110 (fprintf(logfile, "%s: a0=%x a1=%x\n", __func__, a0, a1));
113 /* Used by the tlb decoder. */
114 #define EXTRACT_FIELD(src, start, end) \
115 (((src) >> start) & ((1 << (end - start + 1)) - 1))
117 void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg)
119 uint32_t srs;
120 srs = env->pregs[PR_SRS];
121 srs &= 3;
122 env->sregs[srs][sreg] = env->regs[reg];
124 #if !defined(CONFIG_USER_ONLY)
125 if (srs == 1 || srs == 2) {
126 if (sreg == 6) {
127 /* Writes to tlb-hi write to mm_cause as a side
128 effect. */
129 env->sregs[SFR_RW_MM_TLB_HI] = env->regs[reg];
130 env->sregs[SFR_R_MM_CAUSE] = env->regs[reg];
132 else if (sreg == 5) {
133 uint32_t set;
134 uint32_t idx;
135 uint32_t lo, hi;
136 uint32_t vaddr;
137 int tlb_v;
139 idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
140 set >>= 4;
141 set &= 3;
143 idx &= 15;
144 /* We've just made a write to tlb_lo. */
145 lo = env->sregs[SFR_RW_MM_TLB_LO];
146 /* Writes are done via r_mm_cause. */
147 hi = env->sregs[SFR_R_MM_CAUSE];
149 vaddr = EXTRACT_FIELD(env->tlbsets[srs-1][set][idx].hi,
150 13, 31);
151 vaddr <<= TARGET_PAGE_BITS;
152 tlb_v = EXTRACT_FIELD(env->tlbsets[srs-1][set][idx].lo,
153 3, 3);
154 env->tlbsets[srs - 1][set][idx].lo = lo;
155 env->tlbsets[srs - 1][set][idx].hi = hi;
157 D(fprintf(logfile,
158 "tlb flush vaddr=%x v=%d pc=%x\n",
159 vaddr, tlb_v, env->pc));
160 tlb_flush_page(env, vaddr);
163 #endif
166 void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg)
168 uint32_t srs;
169 env->pregs[PR_SRS] &= 3;
170 srs = env->pregs[PR_SRS];
172 #if !defined(CONFIG_USER_ONLY)
173 if (srs == 1 || srs == 2)
175 uint32_t set;
176 uint32_t idx;
177 uint32_t lo, hi;
179 idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
180 set >>= 4;
181 set &= 3;
182 idx &= 15;
184 /* Update the mirror regs. */
185 hi = env->tlbsets[srs - 1][set][idx].hi;
186 lo = env->tlbsets[srs - 1][set][idx].lo;
187 env->sregs[SFR_RW_MM_TLB_HI] = hi;
188 env->sregs[SFR_RW_MM_TLB_LO] = lo;
190 #endif
191 env->regs[reg] = env->sregs[srs][sreg];
194 static void cris_ccs_rshift(CPUState *env)
196 uint32_t ccs;
198 /* Apply the ccs shift. */
199 ccs = env->pregs[PR_CCS];
200 ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10);
201 if (ccs & U_FLAG)
203 /* Enter user mode. */
204 env->ksp = env->regs[R_SP];
205 env->regs[R_SP] = env->pregs[PR_USP];
208 env->pregs[PR_CCS] = ccs;
211 void helper_rfe(void)
213 int rflag = env->pregs[PR_CCS] & R_FLAG;
215 D(fprintf(logfile, "rfe: erp=%x pid=%x ccs=%x btarget=%x\n",
216 env->pregs[PR_ERP], env->pregs[PR_PID],
217 env->pregs[PR_CCS],
218 env->btarget));
220 cris_ccs_rshift(env);
222 /* RFE sets the P_FLAG only if the R_FLAG is not set. */
223 if (!rflag)
224 env->pregs[PR_CCS] |= P_FLAG;
227 void helper_rfn(void)
229 int rflag = env->pregs[PR_CCS] & R_FLAG;
231 D(fprintf(logfile, "rfn: erp=%x pid=%x ccs=%x btarget=%x\n",
232 env->pregs[PR_ERP], env->pregs[PR_PID],
233 env->pregs[PR_CCS],
234 env->btarget));
236 cris_ccs_rshift(env);
238 /* Set the P_FLAG only if the R_FLAG is not set. */
239 if (!rflag)
240 env->pregs[PR_CCS] |= P_FLAG;
242 /* Always set the M flag. */
243 env->pregs[PR_CCS] |= M_FLAG;
246 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
247 int is_asi, int size)
249 D(printf("%s addr=%x w=%d ex=%d asi=%d, size=%d\n",
250 __func__, addr, is_write, is_exec, is_asi, size));
253 static void evaluate_flags_writeback(uint32_t flags)
255 int x;
257 /* Extended arithmetics, leave the z flag alone. */
258 x = env->cc_x;
259 if ((x || env->cc_op == CC_OP_ADDC)
260 && flags & Z_FLAG)
261 env->cc_mask &= ~Z_FLAG;
263 /* all insn clear the x-flag except setf or clrf. */
264 env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG);
265 flags &= env->cc_mask;
266 env->pregs[PR_CCS] |= flags;
269 void helper_evaluate_flags_muls(void)
271 uint32_t src;
272 uint32_t dst;
273 uint32_t res;
274 uint32_t flags = 0;
275 int64_t tmp;
276 int32_t mof;
277 int dneg;
279 src = env->cc_src;
280 dst = env->cc_dest;
281 res = env->cc_result;
283 dneg = ((int32_t)res) < 0;
285 mof = env->pregs[PR_MOF];
286 tmp = mof;
287 tmp <<= 32;
288 tmp |= res;
289 if (tmp == 0)
290 flags |= Z_FLAG;
291 else if (tmp < 0)
292 flags |= N_FLAG;
293 if ((dneg && mof != -1)
294 || (!dneg && mof != 0))
295 flags |= V_FLAG;
296 evaluate_flags_writeback(flags);
299 void helper_evaluate_flags_mulu(void)
301 uint32_t src;
302 uint32_t dst;
303 uint32_t res;
304 uint32_t flags = 0;
305 uint64_t tmp;
306 uint32_t mof;
308 src = env->cc_src;
309 dst = env->cc_dest;
310 res = env->cc_result;
312 mof = env->pregs[PR_MOF];
313 tmp = mof;
314 tmp <<= 32;
315 tmp |= res;
316 if (tmp == 0)
317 flags |= Z_FLAG;
318 else if (tmp >> 63)
319 flags |= N_FLAG;
320 if (mof)
321 flags |= V_FLAG;
323 evaluate_flags_writeback(flags);
326 void helper_evaluate_flags_mcp(void)
328 uint32_t src;
329 uint32_t dst;
330 uint32_t res;
331 uint32_t flags = 0;
333 src = env->cc_src;
334 dst = env->cc_dest;
335 res = env->cc_result;
337 if ((res & 0x80000000L) != 0L)
339 flags |= N_FLAG;
340 if (((src & 0x80000000L) == 0L)
341 && ((dst & 0x80000000L) == 0L))
343 flags |= V_FLAG;
345 else if (((src & 0x80000000L) != 0L) &&
346 ((dst & 0x80000000L) != 0L))
348 flags |= R_FLAG;
351 else
353 if (res == 0L)
354 flags |= Z_FLAG;
355 if (((src & 0x80000000L) != 0L)
356 && ((dst & 0x80000000L) != 0L))
357 flags |= V_FLAG;
358 if ((dst & 0x80000000L) != 0L
359 || (src & 0x80000000L) != 0L)
360 flags |= R_FLAG;
363 evaluate_flags_writeback(flags);
366 void helper_evaluate_flags_alu_4(void)
368 uint32_t src;
369 uint32_t dst;
370 uint32_t res;
371 uint32_t flags = 0;
373 src = env->cc_src;
374 dst = env->cc_dest;
376 /* Reconstruct the result. */
377 switch (env->cc_op)
379 case CC_OP_SUB:
380 res = dst - src;
381 break;
382 case CC_OP_ADD:
383 res = dst + src;
384 break;
385 default:
386 res = env->cc_result;
387 break;
390 if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
391 src = ~src;
393 if ((res & 0x80000000L) != 0L)
395 flags |= N_FLAG;
396 if (((src & 0x80000000L) == 0L)
397 && ((dst & 0x80000000L) == 0L))
399 flags |= V_FLAG;
401 else if (((src & 0x80000000L) != 0L) &&
402 ((dst & 0x80000000L) != 0L))
404 flags |= C_FLAG;
407 else
409 if (res == 0L)
410 flags |= Z_FLAG;
411 if (((src & 0x80000000L) != 0L)
412 && ((dst & 0x80000000L) != 0L))
413 flags |= V_FLAG;
414 if ((dst & 0x80000000L) != 0L
415 || (src & 0x80000000L) != 0L)
416 flags |= C_FLAG;
419 if (env->cc_op == CC_OP_SUB
420 || env->cc_op == CC_OP_CMP) {
421 flags ^= C_FLAG;
423 evaluate_flags_writeback(flags);
426 void helper_evaluate_flags_move_4 (void)
428 uint32_t res;
429 uint32_t flags = 0;
431 res = env->cc_result;
433 if ((int32_t)res < 0)
434 flags |= N_FLAG;
435 else if (res == 0L)
436 flags |= Z_FLAG;
438 evaluate_flags_writeback(flags);
440 void helper_evaluate_flags_move_2 (void)
442 uint32_t src;
443 uint32_t flags = 0;
444 uint16_t res;
446 src = env->cc_src;
447 res = env->cc_result;
449 if ((int16_t)res < 0L)
450 flags |= N_FLAG;
451 else if (res == 0)
452 flags |= Z_FLAG;
454 evaluate_flags_writeback(flags);
457 /* TODO: This is expensive. We could split things up and only evaluate part of
458 CCR on a need to know basis. For now, we simply re-evaluate everything. */
459 void helper_evaluate_flags (void)
461 uint32_t src;
462 uint32_t dst;
463 uint32_t res;
464 uint32_t flags = 0;
466 src = env->cc_src;
467 dst = env->cc_dest;
468 res = env->cc_result;
470 if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
471 src = ~src;
473 /* Now, evaluate the flags. This stuff is based on
474 Per Zander's CRISv10 simulator. */
475 switch (env->cc_size)
477 case 1:
478 if ((res & 0x80L) != 0L)
480 flags |= N_FLAG;
481 if (((src & 0x80L) == 0L)
482 && ((dst & 0x80L) == 0L))
484 flags |= V_FLAG;
486 else if (((src & 0x80L) != 0L)
487 && ((dst & 0x80L) != 0L))
489 flags |= C_FLAG;
492 else
494 if ((res & 0xFFL) == 0L)
496 flags |= Z_FLAG;
498 if (((src & 0x80L) != 0L)
499 && ((dst & 0x80L) != 0L))
501 flags |= V_FLAG;
503 if ((dst & 0x80L) != 0L
504 || (src & 0x80L) != 0L)
506 flags |= C_FLAG;
509 break;
510 case 2:
511 if ((res & 0x8000L) != 0L)
513 flags |= N_FLAG;
514 if (((src & 0x8000L) == 0L)
515 && ((dst & 0x8000L) == 0L))
517 flags |= V_FLAG;
519 else if (((src & 0x8000L) != 0L)
520 && ((dst & 0x8000L) != 0L))
522 flags |= C_FLAG;
525 else
527 if ((res & 0xFFFFL) == 0L)
529 flags |= Z_FLAG;
531 if (((src & 0x8000L) != 0L)
532 && ((dst & 0x8000L) != 0L))
534 flags |= V_FLAG;
536 if ((dst & 0x8000L) != 0L
537 || (src & 0x8000L) != 0L)
539 flags |= C_FLAG;
542 break;
543 case 4:
544 if ((res & 0x80000000L) != 0L)
546 flags |= N_FLAG;
547 if (((src & 0x80000000L) == 0L)
548 && ((dst & 0x80000000L) == 0L))
550 flags |= V_FLAG;
552 else if (((src & 0x80000000L) != 0L) &&
553 ((dst & 0x80000000L) != 0L))
555 flags |= C_FLAG;
558 else
560 if (res == 0L)
561 flags |= Z_FLAG;
562 if (((src & 0x80000000L) != 0L)
563 && ((dst & 0x80000000L) != 0L))
564 flags |= V_FLAG;
565 if ((dst & 0x80000000L) != 0L
566 || (src & 0x80000000L) != 0L)
567 flags |= C_FLAG;
569 break;
570 default:
571 break;
574 if (env->cc_op == CC_OP_SUB
575 || env->cc_op == CC_OP_CMP) {
576 flags ^= C_FLAG;
578 evaluate_flags_writeback(flags);
581 void helper_top_evaluate_flags(void)
583 switch (env->cc_op)
585 case CC_OP_MCP:
586 helper_evaluate_flags_mcp();
587 break;
588 case CC_OP_MULS:
589 helper_evaluate_flags_muls();
590 break;
591 case CC_OP_MULU:
592 helper_evaluate_flags_mulu();
593 break;
594 case CC_OP_MOVE:
595 case CC_OP_AND:
596 case CC_OP_OR:
597 case CC_OP_XOR:
598 case CC_OP_ASR:
599 case CC_OP_LSR:
600 case CC_OP_LSL:
601 switch (env->cc_size)
603 case 4:
604 helper_evaluate_flags_move_4();
605 break;
606 case 2:
607 helper_evaluate_flags_move_2();
608 break;
609 default:
610 helper_evaluate_flags();
611 break;
613 break;
614 case CC_OP_FLAGS:
615 /* live. */
616 break;
617 default:
619 switch (env->cc_size)
621 case 4:
622 helper_evaluate_flags_alu_4();
623 break;
624 default:
625 helper_evaluate_flags();
626 break;
629 break;