|
|
1.1 root 1: /*
2: * CRIS helper routines
3: *
4: * Copyright (c) 2007 AXIS Communications
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:
1.1.1.7 ! root 21: #include "cpu.h"
! 22: #include "dyngen-exec.h"
1.1.1.2 root 23: #include "mmu.h"
24: #include "helper.h"
25: #include "host-utils.h"
1.1 root 26:
1.1.1.2 root 27: //#define CRIS_OP_HELPER_DEBUG
28:
29:
30: #ifdef CRIS_OP_HELPER_DEBUG
31: #define D(x) x
32: #define D_LOG(...) qemu_log(__VA__ARGS__)
1.1 root 33: #else
1.1.1.2 root 34: #define D(x)
35: #define D_LOG(...) do { } while (0)
1.1 root 36: #endif
37:
1.1.1.2 root 38: #if !defined(CONFIG_USER_ONLY)
1.1.1.7 ! root 39: #include "softmmu_exec.h"
1.1.1.2 root 40:
41: #define MMUSUFFIX _mmu
42:
1.1 root 43: #define SHIFT 0
44: #include "softmmu_template.h"
45:
46: #define SHIFT 1
47: #include "softmmu_template.h"
48:
49: #define SHIFT 2
50: #include "softmmu_template.h"
51:
52: #define SHIFT 3
53: #include "softmmu_template.h"
54:
55: /* Try to fill the TLB and return an exception if error. If retaddr is
56: NULL, it means that the function was called in C code (i.e. not
57: from generated code or from helper.c) */
58: /* XXX: fix it to restore all registers */
1.1.1.7 ! root 59: void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
! 60: void *retaddr)
1.1 root 61: {
62: TranslationBlock *tb;
63: CPUState *saved_env;
64: unsigned long pc;
65: int ret;
66:
67: saved_env = env;
1.1.1.7 ! root 68: env = env1;
1.1.1.2 root 69:
70: D_LOG("%s pc=%x tpc=%x ra=%x\n", __func__,
71: env->pc, env->debug1, retaddr);
1.1.1.7 ! root 72: ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx);
1.1.1.2 root 73: if (unlikely(ret)) {
1.1 root 74: if (retaddr) {
75: /* now we have a real cpu fault */
76: pc = (unsigned long)retaddr;
77: tb = tb_find_pc(pc);
78: if (tb) {
79: /* the PC is inside the translated code. It means that we have
80: a virtual CPU fault */
1.1.1.6 root 81: cpu_restore_state(tb, env, pc);
1.1.1.2 root 82:
83: /* Evaluate flags after retranslation. */
84: helper_top_evaluate_flags();
1.1 root 85: }
86: }
1.1.1.6 root 87: cpu_loop_exit(env);
1.1 root 88: }
89: env = saved_env;
90: }
91:
1.1.1.2 root 92: #endif
93:
94: void helper_raise_exception(uint32_t index)
95: {
96: env->exception_index = index;
1.1.1.6 root 97: cpu_loop_exit(env);
1.1.1.2 root 98: }
99:
100: void helper_tlb_flush_pid(uint32_t pid)
101: {
102: #if !defined(CONFIG_USER_ONLY)
103: pid &= 0xff;
104: if (pid != (env->pregs[PR_PID] & 0xff))
105: cris_mmu_flush_pid(env, env->pregs[PR_PID]);
106: #endif
107: }
108:
109: void helper_spc_write(uint32_t new_spc)
110: {
111: #if !defined(CONFIG_USER_ONLY)
112: tlb_flush_page(env, env->pregs[PR_SPC]);
113: tlb_flush_page(env, new_spc);
114: #endif
115: }
116:
117: void helper_dump(uint32_t a0, uint32_t a1, uint32_t a2)
118: {
119: qemu_log("%s: a0=%x a1=%x\n", __func__, a0, a1);
120: }
121:
122: /* Used by the tlb decoder. */
123: #define EXTRACT_FIELD(src, start, end) \
124: (((src) >> start) & ((1 << (end - start + 1)) - 1))
125:
126: void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg)
127: {
128: uint32_t srs;
129: srs = env->pregs[PR_SRS];
130: srs &= 3;
131: env->sregs[srs][sreg] = env->regs[reg];
132:
133: #if !defined(CONFIG_USER_ONLY)
134: if (srs == 1 || srs == 2) {
135: if (sreg == 6) {
136: /* Writes to tlb-hi write to mm_cause as a side
137: effect. */
138: env->sregs[SFR_RW_MM_TLB_HI] = env->regs[reg];
139: env->sregs[SFR_R_MM_CAUSE] = env->regs[reg];
140: }
141: else if (sreg == 5) {
142: uint32_t set;
143: uint32_t idx;
144: uint32_t lo, hi;
145: uint32_t vaddr;
146: int tlb_v;
147:
148: idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
149: set >>= 4;
150: set &= 3;
151:
152: idx &= 15;
153: /* We've just made a write to tlb_lo. */
154: lo = env->sregs[SFR_RW_MM_TLB_LO];
155: /* Writes are done via r_mm_cause. */
156: hi = env->sregs[SFR_R_MM_CAUSE];
157:
158: vaddr = EXTRACT_FIELD(env->tlbsets[srs-1][set][idx].hi,
159: 13, 31);
160: vaddr <<= TARGET_PAGE_BITS;
161: tlb_v = EXTRACT_FIELD(env->tlbsets[srs-1][set][idx].lo,
162: 3, 3);
163: env->tlbsets[srs - 1][set][idx].lo = lo;
164: env->tlbsets[srs - 1][set][idx].hi = hi;
165:
166: D_LOG("tlb flush vaddr=%x v=%d pc=%x\n",
167: vaddr, tlb_v, env->pc);
1.1.1.5 root 168: if (tlb_v) {
169: tlb_flush_page(env, vaddr);
170: }
1.1.1.2 root 171: }
172: }
173: #endif
174: }
175:
176: void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg)
177: {
178: uint32_t srs;
179: env->pregs[PR_SRS] &= 3;
180: srs = env->pregs[PR_SRS];
181:
182: #if !defined(CONFIG_USER_ONLY)
183: if (srs == 1 || srs == 2)
184: {
185: uint32_t set;
186: uint32_t idx;
187: uint32_t lo, hi;
188:
189: idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
190: set >>= 4;
191: set &= 3;
192: idx &= 15;
193:
194: /* Update the mirror regs. */
195: hi = env->tlbsets[srs - 1][set][idx].hi;
196: lo = env->tlbsets[srs - 1][set][idx].lo;
197: env->sregs[SFR_RW_MM_TLB_HI] = hi;
198: env->sregs[SFR_RW_MM_TLB_LO] = lo;
199: }
200: #endif
201: env->regs[reg] = env->sregs[srs][sreg];
202: }
203:
204: static void cris_ccs_rshift(CPUState *env)
205: {
206: uint32_t ccs;
207:
208: /* Apply the ccs shift. */
209: ccs = env->pregs[PR_CCS];
210: ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10);
211: if (ccs & U_FLAG)
212: {
213: /* Enter user mode. */
214: env->ksp = env->regs[R_SP];
215: env->regs[R_SP] = env->pregs[PR_USP];
216: }
217:
218: env->pregs[PR_CCS] = ccs;
219: }
220:
221: void helper_rfe(void)
222: {
223: int rflag = env->pregs[PR_CCS] & R_FLAG;
224:
225: D_LOG("rfe: erp=%x pid=%x ccs=%x btarget=%x\n",
226: env->pregs[PR_ERP], env->pregs[PR_PID],
227: env->pregs[PR_CCS],
228: env->btarget);
229:
230: cris_ccs_rshift(env);
231:
232: /* RFE sets the P_FLAG only if the R_FLAG is not set. */
233: if (!rflag)
234: env->pregs[PR_CCS] |= P_FLAG;
235: }
236:
237: void helper_rfn(void)
238: {
239: int rflag = env->pregs[PR_CCS] & R_FLAG;
240:
241: D_LOG("rfn: erp=%x pid=%x ccs=%x btarget=%x\n",
242: env->pregs[PR_ERP], env->pregs[PR_PID],
243: env->pregs[PR_CCS],
244: env->btarget);
245:
246: cris_ccs_rshift(env);
247:
248: /* Set the P_FLAG only if the R_FLAG is not set. */
249: if (!rflag)
250: env->pregs[PR_CCS] |= P_FLAG;
251:
252: /* Always set the M flag. */
253: env->pregs[PR_CCS] |= M_FLAG;
254: }
255:
256: uint32_t helper_lz(uint32_t t0)
1.1 root 257: {
1.1.1.2 root 258: return clz32(t0);
259: }
260:
261: uint32_t helper_btst(uint32_t t0, uint32_t t1, uint32_t ccs)
262: {
263: /* FIXME: clean this up. */
264:
265: /* des ref:
266: The N flag is set according to the selected bit in the dest reg.
267: The Z flag is set if the selected bit and all bits to the right are
268: zero.
269: The X flag is cleared.
270: Other flags are left untouched.
271: The destination reg is not affected.*/
272: unsigned int fz, sbit, bset, mask, masked_t0;
273:
274: sbit = t1 & 31;
275: bset = !!(t0 & (1 << sbit));
276: mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1;
277: masked_t0 = t0 & mask;
278: fz = !(masked_t0 | bset);
279:
280: /* Clear the X, N and Z flags. */
281: ccs = ccs & ~(X_FLAG | N_FLAG | Z_FLAG);
1.1.1.4 root 282: if (env->pregs[PR_VR] < 32)
283: ccs &= ~(V_FLAG | C_FLAG);
1.1.1.2 root 284: /* Set the N and Z flags accordingly. */
285: ccs |= (bset << 3) | (fz << 2);
286: return ccs;
287: }
288:
289: static inline uint32_t evaluate_flags_writeback(uint32_t flags, uint32_t ccs)
290: {
291: unsigned int x, z, mask;
292:
293: /* Extended arithmetics, leave the z flag alone. */
294: x = env->cc_x;
295: mask = env->cc_mask | X_FLAG;
296: if (x) {
297: z = flags & Z_FLAG;
298: mask = mask & ~z;
299: }
300: flags &= mask;
301:
302: /* all insn clear the x-flag except setf or clrf. */
303: ccs &= ~mask;
304: ccs |= flags;
305: return ccs;
306: }
307:
308: uint32_t helper_evaluate_flags_muls(uint32_t ccs, uint32_t res, uint32_t mof)
309: {
310: uint32_t flags = 0;
311: int64_t tmp;
312: int dneg;
313:
314: dneg = ((int32_t)res) < 0;
315:
316: tmp = mof;
317: tmp <<= 32;
318: tmp |= res;
319: if (tmp == 0)
320: flags |= Z_FLAG;
321: else if (tmp < 0)
322: flags |= N_FLAG;
323: if ((dneg && mof != -1)
324: || (!dneg && mof != 0))
325: flags |= V_FLAG;
326: return evaluate_flags_writeback(flags, ccs);
327: }
328:
329: uint32_t helper_evaluate_flags_mulu(uint32_t ccs, uint32_t res, uint32_t mof)
330: {
331: uint32_t flags = 0;
332: uint64_t tmp;
333:
334: tmp = mof;
335: tmp <<= 32;
336: tmp |= res;
337: if (tmp == 0)
338: flags |= Z_FLAG;
339: else if (tmp >> 63)
340: flags |= N_FLAG;
341: if (mof)
342: flags |= V_FLAG;
343:
344: return evaluate_flags_writeback(flags, ccs);
345: }
346:
347: uint32_t helper_evaluate_flags_mcp(uint32_t ccs,
348: uint32_t src, uint32_t dst, uint32_t res)
349: {
350: uint32_t flags = 0;
351:
352: src = src & 0x80000000;
353: dst = dst & 0x80000000;
354:
355: if ((res & 0x80000000L) != 0L)
356: {
357: flags |= N_FLAG;
358: if (!src && !dst)
359: flags |= V_FLAG;
360: else if (src & dst)
361: flags |= R_FLAG;
362: }
363: else
364: {
365: if (res == 0L)
366: flags |= Z_FLAG;
367: if (src & dst)
368: flags |= V_FLAG;
369: if (dst | src)
370: flags |= R_FLAG;
371: }
372:
373: return evaluate_flags_writeback(flags, ccs);
374: }
375:
376: uint32_t helper_evaluate_flags_alu_4(uint32_t ccs,
377: uint32_t src, uint32_t dst, uint32_t res)
378: {
379: uint32_t flags = 0;
380:
381: src = src & 0x80000000;
382: dst = dst & 0x80000000;
383:
384: if ((res & 0x80000000L) != 0L)
385: {
386: flags |= N_FLAG;
387: if (!src && !dst)
388: flags |= V_FLAG;
389: else if (src & dst)
390: flags |= C_FLAG;
391: }
392: else
393: {
394: if (res == 0L)
395: flags |= Z_FLAG;
396: if (src & dst)
397: flags |= V_FLAG;
398: if (dst | src)
399: flags |= C_FLAG;
400: }
401:
402: return evaluate_flags_writeback(flags, ccs);
403: }
404:
405: uint32_t helper_evaluate_flags_sub_4(uint32_t ccs,
406: uint32_t src, uint32_t dst, uint32_t res)
407: {
408: uint32_t flags = 0;
409:
410: src = (~src) & 0x80000000;
411: dst = dst & 0x80000000;
1.1 root 412:
1.1.1.2 root 413: if ((res & 0x80000000L) != 0L)
414: {
415: flags |= N_FLAG;
416: if (!src && !dst)
417: flags |= V_FLAG;
418: else if (src & dst)
419: flags |= C_FLAG;
420: }
421: else
422: {
423: if (res == 0L)
424: flags |= Z_FLAG;
425: if (src & dst)
426: flags |= V_FLAG;
427: if (dst | src)
428: flags |= C_FLAG;
429: }
430:
431: flags ^= C_FLAG;
432: return evaluate_flags_writeback(flags, ccs);
433: }
434:
435: uint32_t helper_evaluate_flags_move_4(uint32_t ccs, uint32_t res)
436: {
437: uint32_t flags = 0;
438:
439: if ((int32_t)res < 0)
440: flags |= N_FLAG;
441: else if (res == 0L)
442: flags |= Z_FLAG;
443:
444: return evaluate_flags_writeback(flags, ccs);
445: }
446: uint32_t helper_evaluate_flags_move_2(uint32_t ccs, uint32_t res)
447: {
448: uint32_t flags = 0;
449:
450: if ((int16_t)res < 0L)
451: flags |= N_FLAG;
452: else if (res == 0)
453: flags |= Z_FLAG;
454:
455: return evaluate_flags_writeback(flags, ccs);
456: }
457:
458: /* TODO: This is expensive. We could split things up and only evaluate part of
459: CCR on a need to know basis. For now, we simply re-evaluate everything. */
460: void helper_evaluate_flags(void)
461: {
462: uint32_t src, dst, res;
463: uint32_t flags = 0;
464:
465: src = env->cc_src;
466: dst = env->cc_dest;
467: res = env->cc_result;
468:
469: if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
470: src = ~src;
471:
472: /* Now, evaluate the flags. This stuff is based on
473: Per Zander's CRISv10 simulator. */
474: switch (env->cc_size)
475: {
476: case 1:
477: if ((res & 0x80L) != 0L)
478: {
479: flags |= N_FLAG;
480: if (((src & 0x80L) == 0L)
481: && ((dst & 0x80L) == 0L))
482: {
483: flags |= V_FLAG;
484: }
485: else if (((src & 0x80L) != 0L)
486: && ((dst & 0x80L) != 0L))
487: {
488: flags |= C_FLAG;
489: }
490: }
491: else
492: {
493: if ((res & 0xFFL) == 0L)
494: {
495: flags |= Z_FLAG;
496: }
497: if (((src & 0x80L) != 0L)
498: && ((dst & 0x80L) != 0L))
499: {
500: flags |= V_FLAG;
501: }
502: if ((dst & 0x80L) != 0L
503: || (src & 0x80L) != 0L)
504: {
505: flags |= C_FLAG;
506: }
507: }
508: break;
509: case 2:
510: if ((res & 0x8000L) != 0L)
511: {
512: flags |= N_FLAG;
513: if (((src & 0x8000L) == 0L)
514: && ((dst & 0x8000L) == 0L))
515: {
516: flags |= V_FLAG;
517: }
518: else if (((src & 0x8000L) != 0L)
519: && ((dst & 0x8000L) != 0L))
520: {
521: flags |= C_FLAG;
522: }
523: }
524: else
525: {
526: if ((res & 0xFFFFL) == 0L)
527: {
528: flags |= Z_FLAG;
529: }
530: if (((src & 0x8000L) != 0L)
531: && ((dst & 0x8000L) != 0L))
532: {
533: flags |= V_FLAG;
534: }
535: if ((dst & 0x8000L) != 0L
536: || (src & 0x8000L) != 0L)
537: {
538: flags |= C_FLAG;
539: }
540: }
541: break;
542: case 4:
543: if ((res & 0x80000000L) != 0L)
544: {
545: flags |= N_FLAG;
546: if (((src & 0x80000000L) == 0L)
547: && ((dst & 0x80000000L) == 0L))
548: {
549: flags |= V_FLAG;
550: }
551: else if (((src & 0x80000000L) != 0L) &&
552: ((dst & 0x80000000L) != 0L))
553: {
554: flags |= C_FLAG;
555: }
556: }
557: else
558: {
559: if (res == 0L)
560: flags |= Z_FLAG;
561: if (((src & 0x80000000L) != 0L)
562: && ((dst & 0x80000000L) != 0L))
563: flags |= V_FLAG;
564: if ((dst & 0x80000000L) != 0L
565: || (src & 0x80000000L) != 0L)
566: flags |= C_FLAG;
567: }
568: break;
569: default:
570: break;
571: }
572:
573: if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
574: flags ^= C_FLAG;
575:
576: env->pregs[PR_CCS] = evaluate_flags_writeback(flags, env->pregs[PR_CCS]);
577: }
578:
579: void helper_top_evaluate_flags(void)
580: {
581: switch (env->cc_op)
582: {
583: case CC_OP_MCP:
584: env->pregs[PR_CCS] = helper_evaluate_flags_mcp(
585: env->pregs[PR_CCS], env->cc_src,
586: env->cc_dest, env->cc_result);
587: break;
588: case CC_OP_MULS:
589: env->pregs[PR_CCS] = helper_evaluate_flags_muls(
590: env->pregs[PR_CCS], env->cc_result,
591: env->pregs[PR_MOF]);
592: break;
593: case CC_OP_MULU:
594: env->pregs[PR_CCS] = helper_evaluate_flags_mulu(
595: env->pregs[PR_CCS], env->cc_result,
596: env->pregs[PR_MOF]);
597: break;
598: case CC_OP_MOVE:
599: case CC_OP_AND:
600: case CC_OP_OR:
601: case CC_OP_XOR:
602: case CC_OP_ASR:
603: case CC_OP_LSR:
604: case CC_OP_LSL:
605: switch (env->cc_size)
606: {
607: case 4:
608: env->pregs[PR_CCS] =
609: helper_evaluate_flags_move_4(
610: env->pregs[PR_CCS],
611: env->cc_result);
612: break;
613: case 2:
614: env->pregs[PR_CCS] =
615: helper_evaluate_flags_move_2(
616: env->pregs[PR_CCS],
617: env->cc_result);
618: break;
619: default:
620: helper_evaluate_flags();
621: break;
622: }
623: break;
624: case CC_OP_FLAGS:
625: /* live. */
626: break;
627: case CC_OP_SUB:
628: case CC_OP_CMP:
629: if (env->cc_size == 4)
630: env->pregs[PR_CCS] =
631: helper_evaluate_flags_sub_4(
632: env->pregs[PR_CCS],
633: env->cc_src, env->cc_dest,
634: env->cc_result);
635: else
636: helper_evaluate_flags();
637: break;
638: default:
639: {
640: switch (env->cc_size)
641: {
642: case 4:
643: env->pregs[PR_CCS] =
644: helper_evaluate_flags_alu_4(
645: env->pregs[PR_CCS],
646: env->cc_src, env->cc_dest,
647: env->cc_result);
648: break;
649: default:
650: helper_evaluate_flags();
651: break;
652: }
653: }
654: break;
655: }
1.1 root 656: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.