|
|
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
17: * License along with this library; if not, write to the Free Software
1.1.1.4 ! root 18: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
1.1 root 19: */
20: #include <assert.h>
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:
! 125: uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
1.1 root 126: {
127: uint32_t tmp0, tmp1;
128:
1.1.1.4 ! root 129: tmp1 = arg0 + arg1;
! 130: tmp0 = arg1;
! 131: arg1 = tmp1 + (env->sr & 1);
1.1 root 132: if (tmp0 > tmp1)
133: env->sr |= SR_T;
134: else
135: env->sr &= ~SR_T;
1.1.1.4 ! root 136: if (tmp1 > arg1)
1.1 root 137: env->sr |= SR_T;
1.1.1.4 ! root 138: return arg1;
1.1 root 139: }
140:
1.1.1.4 ! root 141: uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
1.1 root 142: {
143: uint32_t dest, src, ans;
144:
1.1.1.4 ! root 145: if ((int32_t) arg1 >= 0)
1.1 root 146: dest = 0;
147: else
148: dest = 1;
1.1.1.4 ! root 149: if ((int32_t) arg0 >= 0)
1.1 root 150: src = 0;
151: else
152: src = 1;
153: src += dest;
1.1.1.4 ! root 154: arg1 += arg0;
! 155: if ((int32_t) arg1 >= 0)
1.1 root 156: ans = 0;
157: else
158: ans = 1;
159: ans += dest;
160: if (src == 0 || src == 2) {
161: if (ans == 1)
162: env->sr |= SR_T;
163: else
164: env->sr &= ~SR_T;
165: } else
166: env->sr &= ~SR_T;
1.1.1.4 ! root 167: return arg1;
1.1 root 168: }
169:
170: #define T (env->sr & SR_T)
171: #define Q (env->sr & SR_Q ? 1 : 0)
172: #define M (env->sr & SR_M ? 1 : 0)
173: #define SETT env->sr |= SR_T
174: #define CLRT env->sr &= ~SR_T
175: #define SETQ env->sr |= SR_Q
176: #define CLRQ env->sr &= ~SR_Q
177: #define SETM env->sr |= SR_M
178: #define CLRM env->sr &= ~SR_M
179:
1.1.1.4 ! root 180: uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
1.1 root 181: {
182: uint32_t tmp0, tmp2;
183: uint8_t old_q, tmp1 = 0xff;
184:
1.1.1.4 ! root 185: //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
1.1 root 186: old_q = Q;
1.1.1.4 ! root 187: if ((0x80000000 & arg1) != 0)
1.1 root 188: SETQ;
189: else
190: CLRQ;
1.1.1.4 ! root 191: tmp2 = arg0;
! 192: arg1 <<= 1;
! 193: arg1 |= T;
1.1 root 194: switch (old_q) {
195: case 0:
196: switch (M) {
197: case 0:
1.1.1.4 ! root 198: tmp0 = arg1;
! 199: arg1 -= tmp2;
! 200: tmp1 = arg1 > tmp0;
1.1 root 201: switch (Q) {
202: case 0:
203: if (tmp1)
204: SETQ;
205: else
206: CLRQ;
207: break;
208: case 1:
209: if (tmp1 == 0)
210: SETQ;
211: else
212: CLRQ;
213: break;
214: }
215: break;
216: case 1:
1.1.1.4 ! root 217: tmp0 = arg1;
! 218: arg1 += tmp2;
! 219: tmp1 = arg1 < tmp0;
1.1 root 220: switch (Q) {
221: case 0:
222: if (tmp1 == 0)
223: SETQ;
224: else
225: CLRQ;
226: break;
227: case 1:
228: if (tmp1)
229: SETQ;
230: else
231: CLRQ;
232: break;
233: }
234: break;
235: }
236: break;
237: case 1:
238: switch (M) {
239: case 0:
1.1.1.4 ! root 240: tmp0 = arg1;
! 241: arg1 += tmp2;
! 242: tmp1 = arg1 < tmp0;
1.1 root 243: switch (Q) {
244: case 0:
245: if (tmp1)
246: SETQ;
247: else
248: CLRQ;
249: break;
250: case 1:
251: if (tmp1 == 0)
252: SETQ;
253: else
254: CLRQ;
255: break;
256: }
257: break;
258: case 1:
1.1.1.4 ! root 259: tmp0 = arg1;
! 260: arg1 -= tmp2;
! 261: tmp1 = arg1 > tmp0;
1.1 root 262: switch (Q) {
263: case 0:
264: if (tmp1 == 0)
265: SETQ;
266: else
267: CLRQ;
268: break;
269: case 1:
270: if (tmp1)
271: SETQ;
272: else
273: CLRQ;
274: break;
275: }
276: break;
277: }
278: break;
279: }
280: if (Q == M)
281: SETT;
282: else
283: CLRT;
1.1.1.4 ! root 284: //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
! 285: return arg1;
1.1 root 286: }
287:
1.1.1.4 ! root 288: void helper_macl(uint32_t arg0, uint32_t arg1)
1.1 root 289: {
290: int64_t res;
291:
292: res = ((uint64_t) env->mach << 32) | env->macl;
1.1.1.4 ! root 293: res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
1.1 root 294: env->mach = (res >> 32) & 0xffffffff;
295: env->macl = res & 0xffffffff;
296: if (env->sr & SR_S) {
297: if (res < 0)
298: env->mach |= 0xffff0000;
299: else
300: env->mach &= 0x00007fff;
301: }
302: }
303:
1.1.1.4 ! root 304: void helper_macw(uint32_t arg0, uint32_t arg1)
1.1 root 305: {
306: int64_t res;
307:
308: res = ((uint64_t) env->mach << 32) | env->macl;
1.1.1.4 ! root 309: res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
1.1 root 310: env->mach = (res >> 32) & 0xffffffff;
311: env->macl = res & 0xffffffff;
312: if (env->sr & SR_S) {
313: if (res < -0x80000000) {
314: env->mach = 1;
315: env->macl = 0x80000000;
316: } else if (res > 0x000000007fffffff) {
317: env->mach = 1;
318: env->macl = 0x7fffffff;
319: }
320: }
321: }
322:
1.1.1.4 ! root 323: uint32_t helper_negc(uint32_t arg)
1.1 root 324: {
325: uint32_t temp;
326:
1.1.1.4 ! root 327: temp = -arg;
! 328: arg = temp - (env->sr & SR_T);
1.1 root 329: if (0 < temp)
330: env->sr |= SR_T;
331: else
332: env->sr &= ~SR_T;
1.1.1.4 ! root 333: if (temp < arg)
1.1 root 334: env->sr |= SR_T;
1.1.1.4 ! root 335: return arg;
1.1 root 336: }
337:
1.1.1.4 ! root 338: uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
1.1 root 339: {
340: uint32_t tmp0, tmp1;
341:
1.1.1.4 ! root 342: tmp1 = arg1 - arg0;
! 343: tmp0 = arg1;
! 344: arg1 = tmp1 - (env->sr & SR_T);
1.1 root 345: if (tmp0 < tmp1)
346: env->sr |= SR_T;
347: else
348: env->sr &= ~SR_T;
1.1.1.4 ! root 349: if (tmp1 < arg1)
1.1 root 350: env->sr |= SR_T;
1.1.1.4 ! root 351: return arg1;
1.1 root 352: }
353:
1.1.1.4 ! root 354: uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
1.1 root 355: {
356: int32_t dest, src, ans;
357:
1.1.1.4 ! root 358: if ((int32_t) arg1 >= 0)
1.1 root 359: dest = 0;
360: else
361: dest = 1;
1.1.1.4 ! root 362: if ((int32_t) arg0 >= 0)
1.1 root 363: src = 0;
364: else
365: src = 1;
366: src += dest;
1.1.1.4 ! root 367: arg1 -= arg0;
! 368: if ((int32_t) arg1 >= 0)
1.1 root 369: ans = 0;
370: else
371: ans = 1;
372: ans += dest;
373: if (src == 1) {
374: if (ans == 1)
375: env->sr |= SR_T;
376: else
377: env->sr &= ~SR_T;
378: } else
379: env->sr &= ~SR_T;
1.1.1.4 ! root 380: return arg1;
1.1 root 381: }
382:
1.1.1.4 ! root 383: static inline void set_t(void)
1.1 root 384: {
1.1.1.4 ! root 385: env->sr |= SR_T;
! 386: }
1.1 root 387:
1.1.1.4 ! root 388: static inline void clr_t(void)
! 389: {
! 390: env->sr &= ~SR_T;
! 391: }
! 392:
! 393: void helper_ld_fpscr(uint32_t val)
! 394: {
! 395: env->fpscr = val & 0x003fffff;
! 396: if (val & 0x01)
! 397: set_float_rounding_mode(float_round_to_zero, &env->fp_status);
1.1 root 398: else
1.1.1.4 ! root 399: set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1.1 root 400: }
401:
1.1.1.4 ! root 402: uint32_t helper_fabs_FT(uint32_t t0)
1.1 root 403: {
1.1.1.4 ! root 404: CPU_FloatU f;
! 405: f.l = t0;
! 406: f.f = float32_abs(f.f);
! 407: return f.l;
! 408: }
1.1 root 409:
1.1.1.4 ! root 410: uint64_t helper_fabs_DT(uint64_t t0)
! 411: {
! 412: CPU_DoubleU d;
! 413: d.ll = t0;
! 414: d.d = float64_abs(d.d);
! 415: return d.ll;
! 416: }
! 417:
! 418: uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
! 419: {
! 420: CPU_FloatU f0, f1;
! 421: f0.l = t0;
! 422: f1.l = t1;
! 423: f0.f = float32_add(f0.f, f1.f, &env->fp_status);
! 424: return f0.l;
! 425: }
! 426:
! 427: uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
! 428: {
! 429: CPU_DoubleU d0, d1;
! 430: d0.ll = t0;
! 431: d1.ll = t1;
! 432: d0.d = float64_add(d0.d, d1.d, &env->fp_status);
! 433: return d0.ll;
! 434: }
! 435:
! 436: void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
! 437: {
! 438: CPU_FloatU f0, f1;
! 439: f0.l = t0;
! 440: f1.l = t1;
! 441:
! 442: if (float32_compare(f0.f, f1.f, &env->fp_status) == 0)
! 443: set_t();
1.1 root 444: else
1.1.1.4 ! root 445: clr_t();
! 446: }
! 447:
! 448: void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
! 449: {
! 450: CPU_DoubleU d0, d1;
! 451: d0.ll = t0;
! 452: d1.ll = t1;
! 453:
! 454: if (float64_compare(d0.d, d1.d, &env->fp_status) == 0)
! 455: set_t();
! 456: else
! 457: clr_t();
! 458: }
! 459:
! 460: void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
! 461: {
! 462: CPU_FloatU f0, f1;
! 463: f0.l = t0;
! 464: f1.l = t1;
! 465:
! 466: if (float32_compare(f0.f, f1.f, &env->fp_status) == 1)
! 467: set_t();
! 468: else
! 469: clr_t();
! 470: }
! 471:
! 472: void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
! 473: {
! 474: CPU_DoubleU d0, d1;
! 475: d0.ll = t0;
! 476: d1.ll = t1;
! 477:
! 478: if (float64_compare(d0.d, d1.d, &env->fp_status) == 1)
! 479: set_t();
! 480: else
! 481: clr_t();
! 482: }
! 483:
! 484: uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
! 485: {
! 486: CPU_DoubleU d;
! 487: CPU_FloatU f;
! 488: f.l = t0;
! 489: d.d = float32_to_float64(f.f, &env->fp_status);
! 490: return d.ll;
! 491: }
! 492:
! 493: uint32_t helper_fcnvds_DT_FT(uint64_t t0)
! 494: {
! 495: CPU_DoubleU d;
! 496: CPU_FloatU f;
! 497: d.ll = t0;
! 498: f.f = float64_to_float32(d.d, &env->fp_status);
! 499: return f.l;
! 500: }
! 501:
! 502: uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
! 503: {
! 504: CPU_FloatU f0, f1;
! 505: f0.l = t0;
! 506: f1.l = t1;
! 507: f0.f = float32_div(f0.f, f1.f, &env->fp_status);
! 508: return f0.l;
! 509: }
! 510:
! 511: uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
! 512: {
! 513: CPU_DoubleU d0, d1;
! 514: d0.ll = t0;
! 515: d1.ll = t1;
! 516: d0.d = float64_div(d0.d, d1.d, &env->fp_status);
! 517: return d0.ll;
! 518: }
! 519:
! 520: uint32_t helper_float_FT(uint32_t t0)
! 521: {
! 522: CPU_FloatU f;
! 523: f.f = int32_to_float32(t0, &env->fp_status);
! 524: return f.l;
! 525: }
! 526:
! 527: uint64_t helper_float_DT(uint32_t t0)
! 528: {
! 529: CPU_DoubleU d;
! 530: d.d = int32_to_float64(t0, &env->fp_status);
! 531: return d.ll;
! 532: }
! 533:
! 534: uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2)
! 535: {
! 536: CPU_FloatU f0, f1, f2;
! 537: f0.l = t0;
! 538: f1.l = t1;
! 539: f2.l = t2;
! 540: f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
! 541: f0.f = float32_add(f0.f, f2.f, &env->fp_status);
! 542: return f0.l;
! 543: }
! 544:
! 545: uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
! 546: {
! 547: CPU_FloatU f0, f1;
! 548: f0.l = t0;
! 549: f1.l = t1;
! 550: f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
! 551: return f0.l;
! 552: }
! 553:
! 554: uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
! 555: {
! 556: CPU_DoubleU d0, d1;
! 557: d0.ll = t0;
! 558: d1.ll = t1;
! 559: d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
! 560: return d0.ll;
! 561: }
! 562:
! 563: uint32_t helper_fneg_T(uint32_t t0)
! 564: {
! 565: CPU_FloatU f;
! 566: f.l = t0;
! 567: f.f = float32_chs(f.f);
! 568: return f.l;
! 569: }
! 570:
! 571: uint32_t helper_fsqrt_FT(uint32_t t0)
! 572: {
! 573: CPU_FloatU f;
! 574: f.l = t0;
! 575: f.f = float32_sqrt(f.f, &env->fp_status);
! 576: return f.l;
! 577: }
! 578:
! 579: uint64_t helper_fsqrt_DT(uint64_t t0)
! 580: {
! 581: CPU_DoubleU d;
! 582: d.ll = t0;
! 583: d.d = float64_sqrt(d.d, &env->fp_status);
! 584: return d.ll;
! 585: }
! 586:
! 587: uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
! 588: {
! 589: CPU_FloatU f0, f1;
! 590: f0.l = t0;
! 591: f1.l = t1;
! 592: f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
! 593: return f0.l;
! 594: }
! 595:
! 596: uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
! 597: {
! 598: CPU_DoubleU d0, d1;
! 599: d0.ll = t0;
! 600: d1.ll = t1;
! 601: d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
! 602: return d0.ll;
! 603: }
! 604:
! 605: uint32_t helper_ftrc_FT(uint32_t t0)
! 606: {
! 607: CPU_FloatU f;
! 608: f.l = t0;
! 609: return float32_to_int32_round_to_zero(f.f, &env->fp_status);
! 610: }
! 611:
! 612: uint32_t helper_ftrc_DT(uint64_t t0)
! 613: {
! 614: CPU_DoubleU d;
! 615: d.ll = t0;
! 616: return float64_to_int32_round_to_zero(d.d, &env->fp_status);
1.1 root 617: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.