|
|
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:
1.1.1.8 root 24: static void cpu_restore_state_from_retaddr(void *retaddr)
25: {
26: TranslationBlock *tb;
27: unsigned long pc;
28:
29: if (retaddr) {
30: pc = (unsigned long) retaddr;
31: tb = tb_find_pc(pc);
32: if (tb) {
33: /* the PC is inside the translated code. It means that we have
34: a virtual CPU fault */
1.1.1.9 ! root 35: cpu_restore_state(tb, env, pc);
1.1.1.8 root 36: }
37: }
38: }
39:
1.1 root 40: #ifndef CONFIG_USER_ONLY
41:
42: #define MMUSUFFIX _mmu
43:
44: #define SHIFT 0
45: #include "softmmu_template.h"
46:
47: #define SHIFT 1
48: #include "softmmu_template.h"
49:
50: #define SHIFT 2
51: #include "softmmu_template.h"
52:
53: #define SHIFT 3
54: #include "softmmu_template.h"
55:
1.1.1.3 root 56: void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1 root 57: {
58: CPUState *saved_env;
59: int ret;
60:
61: /* XXX: hack to restore env in all cases, even if not called from
62: generated code */
63: saved_env = env;
64: env = cpu_single_env;
1.1.1.3 root 65: ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1 root 66: if (ret) {
1.1.1.8 root 67: /* now we have a real cpu fault */
68: cpu_restore_state_from_retaddr(retaddr);
1.1.1.9 ! root 69: cpu_loop_exit(env);
1.1 root 70: }
71: env = saved_env;
72: }
73:
74: #endif
75:
1.1.1.4 root 76: void helper_ldtlb(void)
77: {
78: #ifdef CONFIG_USER_ONLY
79: /* XXXXX */
1.1.1.7 root 80: cpu_abort(env, "Unhandled ldtlb");
1.1.1.4 root 81: #else
82: cpu_load_tlb(env);
83: #endif
84: }
85:
1.1.1.8 root 86: static inline void raise_exception(int index, void *retaddr)
1.1.1.4 root 87: {
1.1.1.8 root 88: env->exception_index = index;
89: cpu_restore_state_from_retaddr(retaddr);
1.1.1.9 ! root 90: cpu_loop_exit(env);
1.1.1.4 root 91: }
92:
1.1.1.8 root 93: void helper_raise_illegal_instruction(void)
94: {
95: raise_exception(0x180, GETPC());
96: }
97:
1.1.1.4 root 98: void helper_raise_slot_illegal_instruction(void)
99: {
1.1.1.8 root 100: raise_exception(0x1a0, GETPC());
1.1.1.4 root 101: }
102:
103: void helper_raise_fpu_disable(void)
104: {
1.1.1.8 root 105: raise_exception(0x800, GETPC());
1.1.1.4 root 106: }
107:
108: void helper_raise_slot_fpu_disable(void)
109: {
1.1.1.8 root 110: raise_exception(0x820, GETPC());
1.1.1.4 root 111: }
112:
113: void helper_debug(void)
114: {
115: env->exception_index = EXCP_DEBUG;
1.1.1.9 ! root 116: cpu_loop_exit(env);
1.1.1.4 root 117: }
118:
119: void helper_sleep(uint32_t next_pc)
120: {
121: env->halted = 1;
1.1.1.9 ! root 122: env->in_sleep = 1;
1.1.1.4 root 123: env->exception_index = EXCP_HLT;
124: env->pc = next_pc;
1.1.1.9 ! root 125: cpu_loop_exit(env);
1.1.1.4 root 126: }
127:
128: void helper_trapa(uint32_t tra)
129: {
130: env->tra = tra << 2;
1.1.1.8 root 131: raise_exception(0x160, GETPC());
1.1.1.4 root 132: }
133:
1.1.1.5 root 134: void helper_movcal(uint32_t address, uint32_t value)
135: {
136: if (cpu_sh4_is_cached (env, address))
137: {
138: memory_content *r = malloc (sizeof(memory_content));
139: r->address = address;
140: r->value = value;
141: r->next = NULL;
142:
143: *(env->movcal_backup_tail) = r;
144: env->movcal_backup_tail = &(r->next);
145: }
146: }
147:
148: void helper_discard_movcal_backup(void)
149: {
150: memory_content *current = env->movcal_backup;
151:
152: while(current)
153: {
154: memory_content *next = current->next;
155: free (current);
156: env->movcal_backup = current = next;
1.1.1.6 root 157: if (current == NULL)
1.1.1.5 root 158: env->movcal_backup_tail = &(env->movcal_backup);
159: }
160: }
161:
162: void helper_ocbi(uint32_t address)
163: {
164: memory_content **current = &(env->movcal_backup);
165: while (*current)
166: {
167: uint32_t a = (*current)->address;
168: if ((a & ~0x1F) == (address & ~0x1F))
169: {
170: memory_content *next = (*current)->next;
171: stl(a, (*current)->value);
172:
1.1.1.6 root 173: if (next == NULL)
1.1.1.5 root 174: {
175: env->movcal_backup_tail = current;
176: }
177:
178: free (*current);
179: *current = next;
180: break;
181: }
182: }
183: }
184:
1.1.1.4 root 185: uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
1.1 root 186: {
187: uint32_t tmp0, tmp1;
188:
1.1.1.4 root 189: tmp1 = arg0 + arg1;
190: tmp0 = arg1;
191: arg1 = tmp1 + (env->sr & 1);
1.1 root 192: if (tmp0 > tmp1)
193: env->sr |= SR_T;
194: else
195: env->sr &= ~SR_T;
1.1.1.4 root 196: if (tmp1 > arg1)
1.1 root 197: env->sr |= SR_T;
1.1.1.4 root 198: return arg1;
1.1 root 199: }
200:
1.1.1.4 root 201: uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
1.1 root 202: {
203: uint32_t dest, src, ans;
204:
1.1.1.4 root 205: if ((int32_t) arg1 >= 0)
1.1 root 206: dest = 0;
207: else
208: dest = 1;
1.1.1.4 root 209: if ((int32_t) arg0 >= 0)
1.1 root 210: src = 0;
211: else
212: src = 1;
213: src += dest;
1.1.1.4 root 214: arg1 += arg0;
215: if ((int32_t) arg1 >= 0)
1.1 root 216: ans = 0;
217: else
218: ans = 1;
219: ans += dest;
220: if (src == 0 || src == 2) {
221: if (ans == 1)
222: env->sr |= SR_T;
223: else
224: env->sr &= ~SR_T;
225: } else
226: env->sr &= ~SR_T;
1.1.1.4 root 227: return arg1;
1.1 root 228: }
229:
230: #define T (env->sr & SR_T)
231: #define Q (env->sr & SR_Q ? 1 : 0)
232: #define M (env->sr & SR_M ? 1 : 0)
233: #define SETT env->sr |= SR_T
234: #define CLRT env->sr &= ~SR_T
235: #define SETQ env->sr |= SR_Q
236: #define CLRQ env->sr &= ~SR_Q
237: #define SETM env->sr |= SR_M
238: #define CLRM env->sr &= ~SR_M
239:
1.1.1.4 root 240: uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
1.1 root 241: {
242: uint32_t tmp0, tmp2;
243: uint8_t old_q, tmp1 = 0xff;
244:
1.1.1.4 root 245: //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
1.1 root 246: old_q = Q;
1.1.1.4 root 247: if ((0x80000000 & arg1) != 0)
1.1 root 248: SETQ;
249: else
250: CLRQ;
1.1.1.4 root 251: tmp2 = arg0;
252: arg1 <<= 1;
253: arg1 |= T;
1.1 root 254: switch (old_q) {
255: case 0:
256: switch (M) {
257: case 0:
1.1.1.4 root 258: tmp0 = arg1;
259: arg1 -= tmp2;
260: tmp1 = arg1 > tmp0;
1.1 root 261: switch (Q) {
262: case 0:
263: if (tmp1)
264: SETQ;
265: else
266: CLRQ;
267: break;
268: case 1:
269: if (tmp1 == 0)
270: SETQ;
271: else
272: CLRQ;
273: break;
274: }
275: break;
276: case 1:
1.1.1.4 root 277: tmp0 = arg1;
278: arg1 += tmp2;
279: tmp1 = arg1 < tmp0;
1.1 root 280: switch (Q) {
281: case 0:
282: if (tmp1 == 0)
283: SETQ;
284: else
285: CLRQ;
286: break;
287: case 1:
288: if (tmp1)
289: SETQ;
290: else
291: CLRQ;
292: break;
293: }
294: break;
295: }
296: break;
297: case 1:
298: switch (M) {
299: case 0:
1.1.1.4 root 300: tmp0 = arg1;
301: arg1 += tmp2;
302: tmp1 = arg1 < tmp0;
1.1 root 303: switch (Q) {
304: case 0:
305: if (tmp1)
306: SETQ;
307: else
308: CLRQ;
309: break;
310: case 1:
311: if (tmp1 == 0)
312: SETQ;
313: else
314: CLRQ;
315: break;
316: }
317: break;
318: case 1:
1.1.1.4 root 319: tmp0 = arg1;
320: arg1 -= tmp2;
321: tmp1 = arg1 > tmp0;
1.1 root 322: switch (Q) {
323: case 0:
324: if (tmp1 == 0)
325: SETQ;
326: else
327: CLRQ;
328: break;
329: case 1:
330: if (tmp1)
331: SETQ;
332: else
333: CLRQ;
334: break;
335: }
336: break;
337: }
338: break;
339: }
340: if (Q == M)
341: SETT;
342: else
343: CLRT;
1.1.1.4 root 344: //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
345: return arg1;
1.1 root 346: }
347:
1.1.1.4 root 348: void helper_macl(uint32_t arg0, uint32_t arg1)
1.1 root 349: {
350: int64_t res;
351:
352: res = ((uint64_t) env->mach << 32) | env->macl;
1.1.1.4 root 353: res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
1.1 root 354: env->mach = (res >> 32) & 0xffffffff;
355: env->macl = res & 0xffffffff;
356: if (env->sr & SR_S) {
357: if (res < 0)
358: env->mach |= 0xffff0000;
359: else
360: env->mach &= 0x00007fff;
361: }
362: }
363:
1.1.1.4 root 364: void helper_macw(uint32_t arg0, uint32_t arg1)
1.1 root 365: {
366: int64_t res;
367:
368: res = ((uint64_t) env->mach << 32) | env->macl;
1.1.1.4 root 369: res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
1.1 root 370: env->mach = (res >> 32) & 0xffffffff;
371: env->macl = res & 0xffffffff;
372: if (env->sr & SR_S) {
373: if (res < -0x80000000) {
374: env->mach = 1;
375: env->macl = 0x80000000;
376: } else if (res > 0x000000007fffffff) {
377: env->mach = 1;
378: env->macl = 0x7fffffff;
379: }
380: }
381: }
382:
1.1.1.4 root 383: uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
1.1 root 384: {
385: uint32_t tmp0, tmp1;
386:
1.1.1.4 root 387: tmp1 = arg1 - arg0;
388: tmp0 = arg1;
389: arg1 = tmp1 - (env->sr & SR_T);
1.1 root 390: if (tmp0 < tmp1)
391: env->sr |= SR_T;
392: else
393: env->sr &= ~SR_T;
1.1.1.4 root 394: if (tmp1 < arg1)
1.1 root 395: env->sr |= SR_T;
1.1.1.4 root 396: return arg1;
1.1 root 397: }
398:
1.1.1.4 root 399: uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
1.1 root 400: {
401: int32_t dest, src, ans;
402:
1.1.1.4 root 403: if ((int32_t) arg1 >= 0)
1.1 root 404: dest = 0;
405: else
406: dest = 1;
1.1.1.4 root 407: if ((int32_t) arg0 >= 0)
1.1 root 408: src = 0;
409: else
410: src = 1;
411: src += dest;
1.1.1.4 root 412: arg1 -= arg0;
413: if ((int32_t) arg1 >= 0)
1.1 root 414: ans = 0;
415: else
416: ans = 1;
417: ans += dest;
418: if (src == 1) {
419: if (ans == 1)
420: env->sr |= SR_T;
421: else
422: env->sr &= ~SR_T;
423: } else
424: env->sr &= ~SR_T;
1.1.1.4 root 425: return arg1;
1.1 root 426: }
427:
1.1.1.4 root 428: static inline void set_t(void)
1.1 root 429: {
1.1.1.4 root 430: env->sr |= SR_T;
431: }
1.1 root 432:
1.1.1.4 root 433: static inline void clr_t(void)
434: {
435: env->sr &= ~SR_T;
436: }
437:
438: void helper_ld_fpscr(uint32_t val)
439: {
1.1.1.8 root 440: env->fpscr = val & FPSCR_MASK;
441: if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
1.1.1.4 root 442: set_float_rounding_mode(float_round_to_zero, &env->fp_status);
1.1.1.8 root 443: } else {
1.1.1.4 root 444: set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1.1.1.8 root 445: }
446: set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
447: }
448:
449: static void update_fpscr(void *retaddr)
450: {
451: int xcpt, cause, enable;
452:
453: xcpt = get_float_exception_flags(&env->fp_status);
454:
455: /* Clear the flag entries */
456: env->fpscr &= ~FPSCR_FLAG_MASK;
457:
458: if (unlikely(xcpt)) {
459: if (xcpt & float_flag_invalid) {
460: env->fpscr |= FPSCR_FLAG_V;
461: }
462: if (xcpt & float_flag_divbyzero) {
463: env->fpscr |= FPSCR_FLAG_Z;
464: }
465: if (xcpt & float_flag_overflow) {
466: env->fpscr |= FPSCR_FLAG_O;
467: }
468: if (xcpt & float_flag_underflow) {
469: env->fpscr |= FPSCR_FLAG_U;
470: }
471: if (xcpt & float_flag_inexact) {
472: env->fpscr |= FPSCR_FLAG_I;
473: }
474:
475: /* Accumulate in cause entries */
476: env->fpscr |= (env->fpscr & FPSCR_FLAG_MASK)
477: << (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT);
478:
479: /* Generate an exception if enabled */
480: cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
481: enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
482: if (cause & enable) {
483: cpu_restore_state_from_retaddr(retaddr);
484: env->exception_index = 0x120;
1.1.1.9 ! root 485: cpu_loop_exit(env);
1.1.1.8 root 486: }
487: }
1.1 root 488: }
489:
1.1.1.9 ! root 490: float32 helper_fabs_FT(float32 t0)
1.1 root 491: {
1.1.1.9 ! root 492: return float32_abs(t0);
1.1.1.4 root 493: }
1.1 root 494:
1.1.1.9 ! root 495: float64 helper_fabs_DT(float64 t0)
1.1.1.4 root 496: {
1.1.1.9 ! root 497: return float64_abs(t0);
1.1.1.4 root 498: }
499:
1.1.1.9 ! root 500: float32 helper_fadd_FT(float32 t0, float32 t1)
1.1.1.4 root 501: {
1.1.1.8 root 502: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 503: t0 = float32_add(t0, t1, &env->fp_status);
1.1.1.8 root 504: update_fpscr(GETPC());
1.1.1.9 ! root 505: return t0;
1.1.1.4 root 506: }
507:
1.1.1.9 ! root 508: float64 helper_fadd_DT(float64 t0, float64 t1)
1.1.1.4 root 509: {
1.1.1.8 root 510: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 511: t0 = float64_add(t0, t1, &env->fp_status);
1.1.1.8 root 512: update_fpscr(GETPC());
1.1.1.9 ! root 513: return t0;
1.1.1.4 root 514: }
515:
1.1.1.9 ! root 516: void helper_fcmp_eq_FT(float32 t0, float32 t1)
1.1.1.4 root 517: {
1.1.1.8 root 518: int relation;
1.1.1.4 root 519:
1.1.1.8 root 520: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 521: relation = float32_compare(t0, t1, &env->fp_status);
1.1.1.8 root 522: if (unlikely(relation == float_relation_unordered)) {
523: update_fpscr(GETPC());
524: } else if (relation == float_relation_equal) {
1.1.1.4 root 525: set_t();
1.1.1.8 root 526: } else {
1.1.1.4 root 527: clr_t();
1.1.1.8 root 528: }
1.1.1.4 root 529: }
530:
1.1.1.9 ! root 531: void helper_fcmp_eq_DT(float64 t0, float64 t1)
1.1.1.4 root 532: {
1.1.1.8 root 533: int relation;
1.1.1.4 root 534:
1.1.1.8 root 535: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 536: relation = float64_compare(t0, t1, &env->fp_status);
1.1.1.8 root 537: if (unlikely(relation == float_relation_unordered)) {
538: update_fpscr(GETPC());
539: } else if (relation == float_relation_equal) {
1.1.1.4 root 540: set_t();
1.1.1.8 root 541: } else {
1.1.1.4 root 542: clr_t();
1.1.1.8 root 543: }
1.1.1.4 root 544: }
545:
1.1.1.9 ! root 546: void helper_fcmp_gt_FT(float32 t0, float32 t1)
1.1.1.4 root 547: {
1.1.1.8 root 548: int relation;
1.1.1.4 root 549:
1.1.1.8 root 550: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 551: relation = float32_compare(t0, t1, &env->fp_status);
1.1.1.8 root 552: if (unlikely(relation == float_relation_unordered)) {
553: update_fpscr(GETPC());
554: } else if (relation == float_relation_greater) {
1.1.1.4 root 555: set_t();
1.1.1.8 root 556: } else {
1.1.1.4 root 557: clr_t();
1.1.1.8 root 558: }
1.1.1.4 root 559: }
560:
1.1.1.9 ! root 561: void helper_fcmp_gt_DT(float64 t0, float64 t1)
1.1.1.4 root 562: {
1.1.1.8 root 563: int relation;
1.1.1.4 root 564:
1.1.1.8 root 565: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 566: relation = float64_compare(t0, t1, &env->fp_status);
1.1.1.8 root 567: if (unlikely(relation == float_relation_unordered)) {
568: update_fpscr(GETPC());
569: } else if (relation == float_relation_greater) {
1.1.1.4 root 570: set_t();
1.1.1.8 root 571: } else {
1.1.1.4 root 572: clr_t();
1.1.1.8 root 573: }
1.1.1.4 root 574: }
575:
1.1.1.9 ! root 576: float64 helper_fcnvsd_FT_DT(float32 t0)
1.1.1.4 root 577: {
1.1.1.9 ! root 578: float64 ret;
1.1.1.8 root 579: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 580: ret = float32_to_float64(t0, &env->fp_status);
1.1.1.8 root 581: update_fpscr(GETPC());
1.1.1.9 ! root 582: return ret;
1.1.1.4 root 583: }
584:
1.1.1.9 ! root 585: float32 helper_fcnvds_DT_FT(float64 t0)
1.1.1.4 root 586: {
1.1.1.9 ! root 587: float32 ret;
1.1.1.8 root 588: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 589: ret = float64_to_float32(t0, &env->fp_status);
1.1.1.8 root 590: update_fpscr(GETPC());
1.1.1.9 ! root 591: return ret;
1.1.1.4 root 592: }
593:
1.1.1.9 ! root 594: float32 helper_fdiv_FT(float32 t0, float32 t1)
1.1.1.4 root 595: {
1.1.1.8 root 596: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 597: t0 = float32_div(t0, t1, &env->fp_status);
1.1.1.8 root 598: update_fpscr(GETPC());
1.1.1.9 ! root 599: return t0;
1.1.1.4 root 600: }
601:
1.1.1.9 ! root 602: float64 helper_fdiv_DT(float64 t0, float64 t1)
1.1.1.4 root 603: {
1.1.1.8 root 604: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 605: t0 = float64_div(t0, t1, &env->fp_status);
1.1.1.8 root 606: update_fpscr(GETPC());
1.1.1.9 ! root 607: return t0;
1.1.1.4 root 608: }
609:
1.1.1.9 ! root 610: float32 helper_float_FT(uint32_t t0)
1.1.1.4 root 611: {
1.1.1.9 ! root 612: float32 ret;
1.1.1.8 root 613: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 614: ret = int32_to_float32(t0, &env->fp_status);
1.1.1.8 root 615: update_fpscr(GETPC());
1.1.1.9 ! root 616: return ret;
1.1.1.4 root 617: }
618:
1.1.1.9 ! root 619: float64 helper_float_DT(uint32_t t0)
1.1.1.4 root 620: {
1.1.1.9 ! root 621: float64 ret;
1.1.1.8 root 622: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 623: ret = int32_to_float64(t0, &env->fp_status);
1.1.1.8 root 624: update_fpscr(GETPC());
1.1.1.9 ! root 625: return ret;
1.1.1.4 root 626: }
627:
1.1.1.9 ! root 628: float32 helper_fmac_FT(float32 t0, float32 t1, float32 t2)
1.1.1.4 root 629: {
1.1.1.8 root 630: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 631: t0 = float32_mul(t0, t1, &env->fp_status);
! 632: t0 = float32_add(t0, t2, &env->fp_status);
1.1.1.8 root 633: update_fpscr(GETPC());
1.1.1.9 ! root 634: return t0;
1.1.1.4 root 635: }
636:
1.1.1.9 ! root 637: float32 helper_fmul_FT(float32 t0, float32 t1)
1.1.1.4 root 638: {
1.1.1.8 root 639: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 640: t0 = float32_mul(t0, t1, &env->fp_status);
1.1.1.8 root 641: update_fpscr(GETPC());
1.1.1.9 ! root 642: return t0;
1.1.1.4 root 643: }
644:
1.1.1.9 ! root 645: float64 helper_fmul_DT(float64 t0, float64 t1)
1.1.1.4 root 646: {
1.1.1.8 root 647: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 648: t0 = float64_mul(t0, t1, &env->fp_status);
1.1.1.8 root 649: update_fpscr(GETPC());
1.1.1.9 ! root 650: return t0;
1.1.1.4 root 651: }
652:
1.1.1.9 ! root 653: float32 helper_fneg_T(float32 t0)
1.1.1.4 root 654: {
1.1.1.9 ! root 655: return float32_chs(t0);
1.1.1.4 root 656: }
657:
1.1.1.9 ! root 658: float32 helper_fsqrt_FT(float32 t0)
1.1.1.4 root 659: {
1.1.1.8 root 660: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 661: t0 = float32_sqrt(t0, &env->fp_status);
1.1.1.8 root 662: update_fpscr(GETPC());
1.1.1.9 ! root 663: return t0;
1.1.1.4 root 664: }
665:
1.1.1.9 ! root 666: float64 helper_fsqrt_DT(float64 t0)
1.1.1.4 root 667: {
1.1.1.8 root 668: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 669: t0 = float64_sqrt(t0, &env->fp_status);
1.1.1.8 root 670: update_fpscr(GETPC());
1.1.1.9 ! root 671: return t0;
1.1.1.4 root 672: }
673:
1.1.1.9 ! root 674: float32 helper_fsub_FT(float32 t0, float32 t1)
1.1.1.4 root 675: {
1.1.1.8 root 676: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 677: t0 = float32_sub(t0, t1, &env->fp_status);
1.1.1.8 root 678: update_fpscr(GETPC());
1.1.1.9 ! root 679: return t0;
1.1.1.4 root 680: }
681:
1.1.1.9 ! root 682: float64 helper_fsub_DT(float64 t0, float64 t1)
1.1.1.4 root 683: {
1.1.1.8 root 684: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 685: t0 = float64_sub(t0, t1, &env->fp_status);
1.1.1.8 root 686: update_fpscr(GETPC());
1.1.1.9 ! root 687: return t0;
1.1.1.4 root 688: }
689:
1.1.1.9 ! root 690: uint32_t helper_ftrc_FT(float32 t0)
1.1.1.4 root 691: {
1.1.1.8 root 692: uint32_t ret;
693: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 694: ret = float32_to_int32_round_to_zero(t0, &env->fp_status);
1.1.1.8 root 695: update_fpscr(GETPC());
696: return ret;
1.1.1.4 root 697: }
698:
1.1.1.9 ! root 699: uint32_t helper_ftrc_DT(float64 t0)
1.1.1.4 root 700: {
1.1.1.8 root 701: uint32_t ret;
702: set_float_exception_flags(0, &env->fp_status);
1.1.1.9 ! root 703: ret = float64_to_int32_round_to_zero(t0, &env->fp_status);
1.1.1.8 root 704: update_fpscr(GETPC());
705: return ret;
706: }
707:
708: void helper_fipr(uint32_t m, uint32_t n)
709: {
710: int bank, i;
711: float32 r, p;
712:
713: bank = (env->sr & FPSCR_FR) ? 16 : 0;
714: r = float32_zero;
715: set_float_exception_flags(0, &env->fp_status);
716:
717: for (i = 0 ; i < 4 ; i++) {
718: p = float32_mul(env->fregs[bank + m + i],
719: env->fregs[bank + n + i],
720: &env->fp_status);
721: r = float32_add(r, p, &env->fp_status);
722: }
723: update_fpscr(GETPC());
724:
725: env->fregs[bank + n + 3] = r;
726: }
727:
728: void helper_ftrv(uint32_t n)
729: {
730: int bank_matrix, bank_vector;
731: int i, j;
732: float32 r[4];
733: float32 p;
734:
735: bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
736: bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
737: set_float_exception_flags(0, &env->fp_status);
738: for (i = 0 ; i < 4 ; i++) {
739: r[i] = float32_zero;
740: for (j = 0 ; j < 4 ; j++) {
741: p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
742: env->fregs[bank_vector + j],
743: &env->fp_status);
744: r[i] = float32_add(r[i], p, &env->fp_status);
745: }
746: }
747: update_fpscr(GETPC());
748:
749: for (i = 0 ; i < 4 ; i++) {
750: env->fregs[bank_vector + i] = r[i];
751: }
1.1 root 752: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.