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