|
|
1.1 root 1: /*
2: * SH4 emulation
1.1.1.3 root 3: *
1.1 root 4: * Copyright (c) 2005 Samuel Tardieu
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
1.1.1.5 root 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 18: */
19: #include <assert.h>
1.1.1.5 root 20: #include <stdlib.h>
1.1 root 21: #include "exec.h"
1.1.1.4 root 22: #include "helper.h"
1.1 root 23:
24: #ifndef CONFIG_USER_ONLY
25:
26: #define MMUSUFFIX _mmu
27:
28: #define SHIFT 0
29: #include "softmmu_template.h"
30:
31: #define SHIFT 1
32: #include "softmmu_template.h"
33:
34: #define SHIFT 2
35: #include "softmmu_template.h"
36:
37: #define SHIFT 3
38: #include "softmmu_template.h"
39:
1.1.1.3 root 40: void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1 root 41: {
42: TranslationBlock *tb;
43: CPUState *saved_env;
44: unsigned long pc;
45: int ret;
46:
47: /* XXX: hack to restore env in all cases, even if not called from
48: generated code */
49: saved_env = env;
50: env = cpu_single_env;
1.1.1.3 root 51: ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1 root 52: if (ret) {
53: if (retaddr) {
54: /* now we have a real cpu fault */
55: pc = (unsigned long) retaddr;
56: tb = tb_find_pc(pc);
57: if (tb) {
58: /* the PC is inside the translated code. It means that we have
59: a virtual CPU fault */
60: cpu_restore_state(tb, env, pc, NULL);
61: }
62: }
1.1.1.4 root 63: cpu_loop_exit();
1.1 root 64: }
65: env = saved_env;
66: }
67:
68: #endif
69:
1.1.1.4 root 70: void helper_ldtlb(void)
71: {
72: #ifdef CONFIG_USER_ONLY
73: /* XXXXX */
74: assert(0);
75: #else
76: cpu_load_tlb(env);
77: #endif
78: }
79:
80: void helper_raise_illegal_instruction(void)
81: {
82: env->exception_index = 0x180;
83: cpu_loop_exit();
84: }
85:
86: void helper_raise_slot_illegal_instruction(void)
87: {
88: env->exception_index = 0x1a0;
89: cpu_loop_exit();
90: }
91:
92: void helper_raise_fpu_disable(void)
93: {
94: env->exception_index = 0x800;
95: cpu_loop_exit();
96: }
97:
98: void helper_raise_slot_fpu_disable(void)
99: {
100: env->exception_index = 0x820;
101: cpu_loop_exit();
102: }
103:
104: void helper_debug(void)
105: {
106: env->exception_index = EXCP_DEBUG;
107: cpu_loop_exit();
108: }
109:
110: void helper_sleep(uint32_t next_pc)
111: {
112: env->halted = 1;
113: env->exception_index = EXCP_HLT;
114: env->pc = next_pc;
115: cpu_loop_exit();
116: }
117:
118: void helper_trapa(uint32_t tra)
119: {
120: env->tra = tra << 2;
121: env->exception_index = 0x160;
122: cpu_loop_exit();
123: }
124:
1.1.1.5 root 125: void helper_movcal(uint32_t address, uint32_t value)
126: {
127: if (cpu_sh4_is_cached (env, address))
128: {
129: memory_content *r = malloc (sizeof(memory_content));
130: r->address = address;
131: r->value = value;
132: r->next = NULL;
133:
134: *(env->movcal_backup_tail) = r;
135: env->movcal_backup_tail = &(r->next);
136: }
137: }
138:
139: void helper_discard_movcal_backup(void)
140: {
141: memory_content *current = env->movcal_backup;
142:
143: while(current)
144: {
145: memory_content *next = current->next;
146: free (current);
147: env->movcal_backup = current = next;
1.1.1.6 ! root 148: if (current == NULL)
1.1.1.5 root 149: env->movcal_backup_tail = &(env->movcal_backup);
150: }
151: }
152:
153: void helper_ocbi(uint32_t address)
154: {
155: memory_content **current = &(env->movcal_backup);
156: while (*current)
157: {
158: uint32_t a = (*current)->address;
159: if ((a & ~0x1F) == (address & ~0x1F))
160: {
161: memory_content *next = (*current)->next;
162: stl(a, (*current)->value);
163:
1.1.1.6 ! root 164: if (next == NULL)
1.1.1.5 root 165: {
166: env->movcal_backup_tail = current;
167: }
168:
169: free (*current);
170: *current = next;
171: break;
172: }
173: }
174: }
175:
1.1.1.4 root 176: uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
1.1 root 177: {
178: uint32_t tmp0, tmp1;
179:
1.1.1.4 root 180: tmp1 = arg0 + arg1;
181: tmp0 = arg1;
182: arg1 = tmp1 + (env->sr & 1);
1.1 root 183: if (tmp0 > tmp1)
184: env->sr |= SR_T;
185: else
186: env->sr &= ~SR_T;
1.1.1.4 root 187: if (tmp1 > arg1)
1.1 root 188: env->sr |= SR_T;
1.1.1.4 root 189: return arg1;
1.1 root 190: }
191:
1.1.1.4 root 192: uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
1.1 root 193: {
194: uint32_t dest, src, ans;
195:
1.1.1.4 root 196: if ((int32_t) arg1 >= 0)
1.1 root 197: dest = 0;
198: else
199: dest = 1;
1.1.1.4 root 200: if ((int32_t) arg0 >= 0)
1.1 root 201: src = 0;
202: else
203: src = 1;
204: src += dest;
1.1.1.4 root 205: arg1 += arg0;
206: if ((int32_t) arg1 >= 0)
1.1 root 207: ans = 0;
208: else
209: ans = 1;
210: ans += dest;
211: if (src == 0 || src == 2) {
212: if (ans == 1)
213: env->sr |= SR_T;
214: else
215: env->sr &= ~SR_T;
216: } else
217: env->sr &= ~SR_T;
1.1.1.4 root 218: return arg1;
1.1 root 219: }
220:
221: #define T (env->sr & SR_T)
222: #define Q (env->sr & SR_Q ? 1 : 0)
223: #define M (env->sr & SR_M ? 1 : 0)
224: #define SETT env->sr |= SR_T
225: #define CLRT env->sr &= ~SR_T
226: #define SETQ env->sr |= SR_Q
227: #define CLRQ env->sr &= ~SR_Q
228: #define SETM env->sr |= SR_M
229: #define CLRM env->sr &= ~SR_M
230:
1.1.1.4 root 231: uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
1.1 root 232: {
233: uint32_t tmp0, tmp2;
234: uint8_t old_q, tmp1 = 0xff;
235:
1.1.1.4 root 236: //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
1.1 root 237: old_q = Q;
1.1.1.4 root 238: if ((0x80000000 & arg1) != 0)
1.1 root 239: SETQ;
240: else
241: CLRQ;
1.1.1.4 root 242: tmp2 = arg0;
243: arg1 <<= 1;
244: arg1 |= T;
1.1 root 245: switch (old_q) {
246: case 0:
247: switch (M) {
248: case 0:
1.1.1.4 root 249: tmp0 = arg1;
250: arg1 -= tmp2;
251: tmp1 = arg1 > tmp0;
1.1 root 252: switch (Q) {
253: case 0:
254: if (tmp1)
255: SETQ;
256: else
257: CLRQ;
258: break;
259: case 1:
260: if (tmp1 == 0)
261: SETQ;
262: else
263: CLRQ;
264: break;
265: }
266: break;
267: case 1:
1.1.1.4 root 268: tmp0 = arg1;
269: arg1 += tmp2;
270: tmp1 = arg1 < tmp0;
1.1 root 271: switch (Q) {
272: case 0:
273: if (tmp1 == 0)
274: SETQ;
275: else
276: CLRQ;
277: break;
278: case 1:
279: if (tmp1)
280: SETQ;
281: else
282: CLRQ;
283: break;
284: }
285: break;
286: }
287: break;
288: case 1:
289: switch (M) {
290: case 0:
1.1.1.4 root 291: tmp0 = arg1;
292: arg1 += tmp2;
293: tmp1 = arg1 < tmp0;
1.1 root 294: switch (Q) {
295: case 0:
296: if (tmp1)
297: SETQ;
298: else
299: CLRQ;
300: break;
301: case 1:
302: if (tmp1 == 0)
303: SETQ;
304: else
305: CLRQ;
306: break;
307: }
308: break;
309: case 1:
1.1.1.4 root 310: tmp0 = arg1;
311: arg1 -= tmp2;
312: tmp1 = arg1 > tmp0;
1.1 root 313: switch (Q) {
314: case 0:
315: if (tmp1 == 0)
316: SETQ;
317: else
318: CLRQ;
319: break;
320: case 1:
321: if (tmp1)
322: SETQ;
323: else
324: CLRQ;
325: break;
326: }
327: break;
328: }
329: break;
330: }
331: if (Q == M)
332: SETT;
333: else
334: CLRT;
1.1.1.4 root 335: //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
336: return arg1;
1.1 root 337: }
338:
1.1.1.4 root 339: void helper_macl(uint32_t arg0, uint32_t arg1)
1.1 root 340: {
341: int64_t res;
342:
343: res = ((uint64_t) env->mach << 32) | env->macl;
1.1.1.4 root 344: res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
1.1 root 345: env->mach = (res >> 32) & 0xffffffff;
346: env->macl = res & 0xffffffff;
347: if (env->sr & SR_S) {
348: if (res < 0)
349: env->mach |= 0xffff0000;
350: else
351: env->mach &= 0x00007fff;
352: }
353: }
354:
1.1.1.4 root 355: void helper_macw(uint32_t arg0, uint32_t arg1)
1.1 root 356: {
357: int64_t res;
358:
359: res = ((uint64_t) env->mach << 32) | env->macl;
1.1.1.4 root 360: res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
1.1 root 361: env->mach = (res >> 32) & 0xffffffff;
362: env->macl = res & 0xffffffff;
363: if (env->sr & SR_S) {
364: if (res < -0x80000000) {
365: env->mach = 1;
366: env->macl = 0x80000000;
367: } else if (res > 0x000000007fffffff) {
368: env->mach = 1;
369: env->macl = 0x7fffffff;
370: }
371: }
372: }
373:
1.1.1.4 root 374: uint32_t helper_negc(uint32_t arg)
1.1 root 375: {
376: uint32_t temp;
377:
1.1.1.4 root 378: temp = -arg;
379: arg = temp - (env->sr & SR_T);
1.1 root 380: if (0 < temp)
381: env->sr |= SR_T;
382: else
383: env->sr &= ~SR_T;
1.1.1.4 root 384: if (temp < arg)
1.1 root 385: env->sr |= SR_T;
1.1.1.4 root 386: return arg;
1.1 root 387: }
388:
1.1.1.4 root 389: uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
1.1 root 390: {
391: uint32_t tmp0, tmp1;
392:
1.1.1.4 root 393: tmp1 = arg1 - arg0;
394: tmp0 = arg1;
395: arg1 = tmp1 - (env->sr & SR_T);
1.1 root 396: if (tmp0 < tmp1)
397: env->sr |= SR_T;
398: else
399: env->sr &= ~SR_T;
1.1.1.4 root 400: if (tmp1 < arg1)
1.1 root 401: env->sr |= SR_T;
1.1.1.4 root 402: return arg1;
1.1 root 403: }
404:
1.1.1.4 root 405: uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
1.1 root 406: {
407: int32_t dest, src, ans;
408:
1.1.1.4 root 409: if ((int32_t) arg1 >= 0)
1.1 root 410: dest = 0;
411: else
412: dest = 1;
1.1.1.4 root 413: if ((int32_t) arg0 >= 0)
1.1 root 414: src = 0;
415: else
416: src = 1;
417: src += dest;
1.1.1.4 root 418: arg1 -= arg0;
419: if ((int32_t) arg1 >= 0)
1.1 root 420: ans = 0;
421: else
422: ans = 1;
423: ans += dest;
424: if (src == 1) {
425: if (ans == 1)
426: env->sr |= SR_T;
427: else
428: env->sr &= ~SR_T;
429: } else
430: env->sr &= ~SR_T;
1.1.1.4 root 431: return arg1;
1.1 root 432: }
433:
1.1.1.4 root 434: static inline void set_t(void)
1.1 root 435: {
1.1.1.4 root 436: env->sr |= SR_T;
437: }
1.1 root 438:
1.1.1.4 root 439: static inline void clr_t(void)
440: {
441: env->sr &= ~SR_T;
442: }
443:
444: void helper_ld_fpscr(uint32_t val)
445: {
446: env->fpscr = val & 0x003fffff;
447: if (val & 0x01)
448: set_float_rounding_mode(float_round_to_zero, &env->fp_status);
1.1 root 449: else
1.1.1.4 root 450: set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1.1 root 451: }
452:
1.1.1.4 root 453: uint32_t helper_fabs_FT(uint32_t t0)
1.1 root 454: {
1.1.1.4 root 455: CPU_FloatU f;
456: f.l = t0;
457: f.f = float32_abs(f.f);
458: return f.l;
459: }
1.1 root 460:
1.1.1.4 root 461: uint64_t helper_fabs_DT(uint64_t t0)
462: {
463: CPU_DoubleU d;
464: d.ll = t0;
465: d.d = float64_abs(d.d);
466: return d.ll;
467: }
468:
469: uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
470: {
471: CPU_FloatU f0, f1;
472: f0.l = t0;
473: f1.l = t1;
474: f0.f = float32_add(f0.f, f1.f, &env->fp_status);
475: return f0.l;
476: }
477:
478: uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
479: {
480: CPU_DoubleU d0, d1;
481: d0.ll = t0;
482: d1.ll = t1;
483: d0.d = float64_add(d0.d, d1.d, &env->fp_status);
484: return d0.ll;
485: }
486:
487: void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
488: {
489: CPU_FloatU f0, f1;
490: f0.l = t0;
491: f1.l = t1;
492:
493: if (float32_compare(f0.f, f1.f, &env->fp_status) == 0)
494: set_t();
1.1 root 495: else
1.1.1.4 root 496: clr_t();
497: }
498:
499: void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
500: {
501: CPU_DoubleU d0, d1;
502: d0.ll = t0;
503: d1.ll = t1;
504:
505: if (float64_compare(d0.d, d1.d, &env->fp_status) == 0)
506: set_t();
507: else
508: clr_t();
509: }
510:
511: void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
512: {
513: CPU_FloatU f0, f1;
514: f0.l = t0;
515: f1.l = t1;
516:
517: if (float32_compare(f0.f, f1.f, &env->fp_status) == 1)
518: set_t();
519: else
520: clr_t();
521: }
522:
523: void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
524: {
525: CPU_DoubleU d0, d1;
526: d0.ll = t0;
527: d1.ll = t1;
528:
529: if (float64_compare(d0.d, d1.d, &env->fp_status) == 1)
530: set_t();
531: else
532: clr_t();
533: }
534:
535: uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
536: {
537: CPU_DoubleU d;
538: CPU_FloatU f;
539: f.l = t0;
540: d.d = float32_to_float64(f.f, &env->fp_status);
541: return d.ll;
542: }
543:
544: uint32_t helper_fcnvds_DT_FT(uint64_t t0)
545: {
546: CPU_DoubleU d;
547: CPU_FloatU f;
548: d.ll = t0;
549: f.f = float64_to_float32(d.d, &env->fp_status);
550: return f.l;
551: }
552:
553: uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
554: {
555: CPU_FloatU f0, f1;
556: f0.l = t0;
557: f1.l = t1;
558: f0.f = float32_div(f0.f, f1.f, &env->fp_status);
559: return f0.l;
560: }
561:
562: uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
563: {
564: CPU_DoubleU d0, d1;
565: d0.ll = t0;
566: d1.ll = t1;
567: d0.d = float64_div(d0.d, d1.d, &env->fp_status);
568: return d0.ll;
569: }
570:
571: uint32_t helper_float_FT(uint32_t t0)
572: {
573: CPU_FloatU f;
574: f.f = int32_to_float32(t0, &env->fp_status);
575: return f.l;
576: }
577:
578: uint64_t helper_float_DT(uint32_t t0)
579: {
580: CPU_DoubleU d;
581: d.d = int32_to_float64(t0, &env->fp_status);
582: return d.ll;
583: }
584:
585: uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2)
586: {
587: CPU_FloatU f0, f1, f2;
588: f0.l = t0;
589: f1.l = t1;
590: f2.l = t2;
591: f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
592: f0.f = float32_add(f0.f, f2.f, &env->fp_status);
593: return f0.l;
594: }
595:
596: uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
597: {
598: CPU_FloatU f0, f1;
599: f0.l = t0;
600: f1.l = t1;
601: f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
602: return f0.l;
603: }
604:
605: uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
606: {
607: CPU_DoubleU d0, d1;
608: d0.ll = t0;
609: d1.ll = t1;
610: d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
611: return d0.ll;
612: }
613:
614: uint32_t helper_fneg_T(uint32_t t0)
615: {
616: CPU_FloatU f;
617: f.l = t0;
618: f.f = float32_chs(f.f);
619: return f.l;
620: }
621:
622: uint32_t helper_fsqrt_FT(uint32_t t0)
623: {
624: CPU_FloatU f;
625: f.l = t0;
626: f.f = float32_sqrt(f.f, &env->fp_status);
627: return f.l;
628: }
629:
630: uint64_t helper_fsqrt_DT(uint64_t t0)
631: {
632: CPU_DoubleU d;
633: d.ll = t0;
634: d.d = float64_sqrt(d.d, &env->fp_status);
635: return d.ll;
636: }
637:
638: uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
639: {
640: CPU_FloatU f0, f1;
641: f0.l = t0;
642: f1.l = t1;
643: f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
644: return f0.l;
645: }
646:
647: uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
648: {
649: CPU_DoubleU d0, d1;
650: d0.ll = t0;
651: d1.ll = t1;
652: d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
653: return d0.ll;
654: }
655:
656: uint32_t helper_ftrc_FT(uint32_t t0)
657: {
658: CPU_FloatU f;
659: f.l = t0;
660: return float32_to_int32_round_to_zero(f.f, &env->fp_status);
661: }
662:
663: uint32_t helper_ftrc_DT(uint64_t t0)
664: {
665: CPU_DoubleU d;
666: d.ll = t0;
667: return float64_to_int32_round_to_zero(d.d, &env->fp_status);
1.1 root 668: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.