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