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