xref: /illumos-kvm-cmd/target-sh4/op_helper.c (revision 68396ea9)
1 /*
2  *  SH4 emulation
3  *
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, see <http://www.gnu.org/licenses/>.
18  */
19 #include <assert.h>
20 #include <stdlib.h>
21 #include "exec.h"
22 #include "helper.h"
23 
cpu_restore_state_from_retaddr(void * retaddr)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 */
35             cpu_restore_state(tb, env, pc, NULL);
36         }
37     }
38 }
39 
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 
tlb_fill(target_ulong addr,int is_write,int mmu_idx,void * retaddr)56 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
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;
65     ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
66     if (ret) {
67         /* now we have a real cpu fault */
68         cpu_restore_state_from_retaddr(retaddr);
69 	cpu_loop_exit();
70     }
71     env = saved_env;
72 }
73 
74 #endif
75 
helper_ldtlb(void)76 void helper_ldtlb(void)
77 {
78 #ifdef CONFIG_USER_ONLY
79     /* XXXXX */
80     cpu_abort(env, "Unhandled ldtlb");
81 #else
82     cpu_load_tlb(env);
83 #endif
84 }
85 
raise_exception(int index,void * retaddr)86 static inline void raise_exception(int index, void *retaddr)
87 {
88     env->exception_index = index;
89     cpu_restore_state_from_retaddr(retaddr);
90     cpu_loop_exit();
91 }
92 
helper_raise_illegal_instruction(void)93 void helper_raise_illegal_instruction(void)
94 {
95     raise_exception(0x180, GETPC());
96 }
97 
helper_raise_slot_illegal_instruction(void)98 void helper_raise_slot_illegal_instruction(void)
99 {
100     raise_exception(0x1a0, GETPC());
101 }
102 
helper_raise_fpu_disable(void)103 void helper_raise_fpu_disable(void)
104 {
105     raise_exception(0x800, GETPC());
106 }
107 
helper_raise_slot_fpu_disable(void)108 void helper_raise_slot_fpu_disable(void)
109 {
110     raise_exception(0x820, GETPC());
111 }
112 
helper_debug(void)113 void helper_debug(void)
114 {
115     env->exception_index = EXCP_DEBUG;
116     cpu_loop_exit();
117 }
118 
helper_sleep(uint32_t next_pc)119 void helper_sleep(uint32_t next_pc)
120 {
121     env->halted = 1;
122     env->exception_index = EXCP_HLT;
123     env->pc = next_pc;
124     cpu_loop_exit();
125 }
126 
helper_trapa(uint32_t tra)127 void helper_trapa(uint32_t tra)
128 {
129     env->tra = tra << 2;
130     raise_exception(0x160, GETPC());
131 }
132 
helper_movcal(uint32_t address,uint32_t value)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 
helper_discard_movcal_backup(void)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;
156 	if (current == NULL)
157 	    env->movcal_backup_tail = &(env->movcal_backup);
158     }
159 }
160 
helper_ocbi(uint32_t address)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 
172 	    if (next == NULL)
173 	    {
174 		env->movcal_backup_tail = current;
175 	    }
176 
177 	    free (*current);
178 	    *current = next;
179 	    break;
180 	}
181     }
182 }
183 
helper_addc(uint32_t arg0,uint32_t arg1)184 uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
185 {
186     uint32_t tmp0, tmp1;
187 
188     tmp1 = arg0 + arg1;
189     tmp0 = arg1;
190     arg1 = tmp1 + (env->sr & 1);
191     if (tmp0 > tmp1)
192 	env->sr |= SR_T;
193     else
194 	env->sr &= ~SR_T;
195     if (tmp1 > arg1)
196 	env->sr |= SR_T;
197     return arg1;
198 }
199 
helper_addv(uint32_t arg0,uint32_t arg1)200 uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
201 {
202     uint32_t dest, src, ans;
203 
204     if ((int32_t) arg1 >= 0)
205 	dest = 0;
206     else
207 	dest = 1;
208     if ((int32_t) arg0 >= 0)
209 	src = 0;
210     else
211 	src = 1;
212     src += dest;
213     arg1 += arg0;
214     if ((int32_t) arg1 >= 0)
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;
226     return arg1;
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 
helper_div1(uint32_t arg0,uint32_t arg1)239 uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
240 {
241     uint32_t tmp0, tmp2;
242     uint8_t old_q, tmp1 = 0xff;
243 
244     //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
245     old_q = Q;
246     if ((0x80000000 & arg1) != 0)
247 	SETQ;
248     else
249 	CLRQ;
250     tmp2 = arg0;
251     arg1 <<= 1;
252     arg1 |= T;
253     switch (old_q) {
254     case 0:
255 	switch (M) {
256 	case 0:
257 	    tmp0 = arg1;
258 	    arg1 -= tmp2;
259 	    tmp1 = arg1 > tmp0;
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:
276 	    tmp0 = arg1;
277 	    arg1 += tmp2;
278 	    tmp1 = arg1 < tmp0;
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:
299 	    tmp0 = arg1;
300 	    arg1 += tmp2;
301 	    tmp1 = arg1 < tmp0;
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:
318 	    tmp0 = arg1;
319 	    arg1 -= tmp2;
320 	    tmp1 = arg1 > tmp0;
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;
343     //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
344     return arg1;
345 }
346 
helper_macl(uint32_t arg0,uint32_t arg1)347 void helper_macl(uint32_t arg0, uint32_t arg1)
348 {
349     int64_t res;
350 
351     res = ((uint64_t) env->mach << 32) | env->macl;
352     res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
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 
helper_macw(uint32_t arg0,uint32_t arg1)363 void helper_macw(uint32_t arg0, uint32_t arg1)
364 {
365     int64_t res;
366 
367     res = ((uint64_t) env->mach << 32) | env->macl;
368     res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
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 
helper_subc(uint32_t arg0,uint32_t arg1)382 uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
383 {
384     uint32_t tmp0, tmp1;
385 
386     tmp1 = arg1 - arg0;
387     tmp0 = arg1;
388     arg1 = tmp1 - (env->sr & SR_T);
389     if (tmp0 < tmp1)
390 	env->sr |= SR_T;
391     else
392 	env->sr &= ~SR_T;
393     if (tmp1 < arg1)
394 	env->sr |= SR_T;
395     return arg1;
396 }
397 
helper_subv(uint32_t arg0,uint32_t arg1)398 uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
399 {
400     int32_t dest, src, ans;
401 
402     if ((int32_t) arg1 >= 0)
403 	dest = 0;
404     else
405 	dest = 1;
406     if ((int32_t) arg0 >= 0)
407 	src = 0;
408     else
409 	src = 1;
410     src += dest;
411     arg1 -= arg0;
412     if ((int32_t) arg1 >= 0)
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;
424     return arg1;
425 }
426 
set_t(void)427 static inline void set_t(void)
428 {
429     env->sr |= SR_T;
430 }
431 
clr_t(void)432 static inline void clr_t(void)
433 {
434     env->sr &= ~SR_T;
435 }
436 
helper_ld_fpscr(uint32_t val)437 void helper_ld_fpscr(uint32_t val)
438 {
439     env->fpscr = val & FPSCR_MASK;
440     if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
441 	set_float_rounding_mode(float_round_to_zero, &env->fp_status);
442     } else {
443 	set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
444     }
445     set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
446 }
447 
update_fpscr(void * retaddr)448 static void update_fpscr(void *retaddr)
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;
484             cpu_loop_exit();
485         }
486     }
487 }
488 
helper_fabs_FT(uint32_t t0)489 uint32_t helper_fabs_FT(uint32_t t0)
490 {
491     CPU_FloatU f;
492     f.l = t0;
493     f.f = float32_abs(f.f);
494     return f.l;
495 }
496 
helper_fabs_DT(uint64_t t0)497 uint64_t helper_fabs_DT(uint64_t t0)
498 {
499     CPU_DoubleU d;
500     d.ll = t0;
501     d.d = float64_abs(d.d);
502     return d.ll;
503 }
504 
helper_fadd_FT(uint32_t t0,uint32_t t1)505 uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
506 {
507     CPU_FloatU f0, f1;
508     f0.l = t0;
509     f1.l = t1;
510     set_float_exception_flags(0, &env->fp_status);
511     f0.f = float32_add(f0.f, f1.f, &env->fp_status);
512     update_fpscr(GETPC());
513     return f0.l;
514 }
515 
helper_fadd_DT(uint64_t t0,uint64_t t1)516 uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
517 {
518     CPU_DoubleU d0, d1;
519     d0.ll = t0;
520     d1.ll = t1;
521     set_float_exception_flags(0, &env->fp_status);
522     d0.d = float64_add(d0.d, d1.d, &env->fp_status);
523     update_fpscr(GETPC());
524     return d0.ll;
525 }
526 
helper_fcmp_eq_FT(uint32_t t0,uint32_t t1)527 void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
528 {
529     CPU_FloatU f0, f1;
530     int relation;
531     f0.l = t0;
532     f1.l = t1;
533 
534     set_float_exception_flags(0, &env->fp_status);
535     relation = float32_compare(f0.f, f1.f, &env->fp_status);
536     if (unlikely(relation == float_relation_unordered)) {
537         update_fpscr(GETPC());
538     } else if (relation == float_relation_equal) {
539 	set_t();
540     } else {
541 	clr_t();
542     }
543 }
544 
helper_fcmp_eq_DT(uint64_t t0,uint64_t t1)545 void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
546 {
547     CPU_DoubleU d0, d1;
548     int relation;
549     d0.ll = t0;
550     d1.ll = t1;
551 
552     set_float_exception_flags(0, &env->fp_status);
553     relation = float64_compare(d0.d, d1.d, &env->fp_status);
554     if (unlikely(relation == float_relation_unordered)) {
555         update_fpscr(GETPC());
556     } else if (relation == float_relation_equal) {
557 	set_t();
558     } else {
559 	clr_t();
560     }
561 }
562 
helper_fcmp_gt_FT(uint32_t t0,uint32_t t1)563 void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
564 {
565     CPU_FloatU f0, f1;
566     int relation;
567     f0.l = t0;
568     f1.l = t1;
569 
570     set_float_exception_flags(0, &env->fp_status);
571     relation = float32_compare(f0.f, f1.f, &env->fp_status);
572     if (unlikely(relation == float_relation_unordered)) {
573         update_fpscr(GETPC());
574     } else if (relation == float_relation_greater) {
575 	set_t();
576     } else {
577 	clr_t();
578     }
579 }
580 
helper_fcmp_gt_DT(uint64_t t0,uint64_t t1)581 void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
582 {
583     CPU_DoubleU d0, d1;
584     int relation;
585     d0.ll = t0;
586     d1.ll = t1;
587 
588     set_float_exception_flags(0, &env->fp_status);
589     relation = float64_compare(d0.d, d1.d, &env->fp_status);
590     if (unlikely(relation == float_relation_unordered)) {
591         update_fpscr(GETPC());
592     } else if (relation == float_relation_greater) {
593 	set_t();
594     } else {
595 	clr_t();
596     }
597 }
598 
helper_fcnvsd_FT_DT(uint32_t t0)599 uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
600 {
601     CPU_DoubleU d;
602     CPU_FloatU f;
603     f.l = t0;
604     set_float_exception_flags(0, &env->fp_status);
605     d.d = float32_to_float64(f.f, &env->fp_status);
606     update_fpscr(GETPC());
607     return d.ll;
608 }
609 
helper_fcnvds_DT_FT(uint64_t t0)610 uint32_t helper_fcnvds_DT_FT(uint64_t t0)
611 {
612     CPU_DoubleU d;
613     CPU_FloatU f;
614     d.ll = t0;
615     set_float_exception_flags(0, &env->fp_status);
616     f.f = float64_to_float32(d.d, &env->fp_status);
617     update_fpscr(GETPC());
618     return f.l;
619 }
620 
helper_fdiv_FT(uint32_t t0,uint32_t t1)621 uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
622 {
623     CPU_FloatU f0, f1;
624     f0.l = t0;
625     f1.l = t1;
626     set_float_exception_flags(0, &env->fp_status);
627     f0.f = float32_div(f0.f, f1.f, &env->fp_status);
628     update_fpscr(GETPC());
629     return f0.l;
630 }
631 
helper_fdiv_DT(uint64_t t0,uint64_t t1)632 uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
633 {
634     CPU_DoubleU d0, d1;
635     d0.ll = t0;
636     d1.ll = t1;
637     set_float_exception_flags(0, &env->fp_status);
638     d0.d = float64_div(d0.d, d1.d, &env->fp_status);
639     update_fpscr(GETPC());
640     return d0.ll;
641 }
642 
helper_float_FT(uint32_t t0)643 uint32_t helper_float_FT(uint32_t t0)
644 {
645     CPU_FloatU f;
646 
647     set_float_exception_flags(0, &env->fp_status);
648     f.f = int32_to_float32(t0, &env->fp_status);
649     update_fpscr(GETPC());
650 
651     return f.l;
652 }
653 
helper_float_DT(uint32_t t0)654 uint64_t helper_float_DT(uint32_t t0)
655 {
656     CPU_DoubleU d;
657     set_float_exception_flags(0, &env->fp_status);
658     d.d = int32_to_float64(t0, &env->fp_status);
659     update_fpscr(GETPC());
660     return d.ll;
661 }
662 
helper_fmac_FT(uint32_t t0,uint32_t t1,uint32_t t2)663 uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2)
664 {
665     CPU_FloatU f0, f1, f2;
666     f0.l = t0;
667     f1.l = t1;
668     f2.l = t2;
669     set_float_exception_flags(0, &env->fp_status);
670     f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
671     f0.f = float32_add(f0.f, f2.f, &env->fp_status);
672     update_fpscr(GETPC());
673 
674     return f0.l;
675 }
676 
helper_fmul_FT(uint32_t t0,uint32_t t1)677 uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
678 {
679     CPU_FloatU f0, f1;
680     f0.l = t0;
681     f1.l = t1;
682     set_float_exception_flags(0, &env->fp_status);
683     f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
684     update_fpscr(GETPC());
685     return f0.l;
686 }
687 
helper_fmul_DT(uint64_t t0,uint64_t t1)688 uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
689 {
690     CPU_DoubleU d0, d1;
691     d0.ll = t0;
692     d1.ll = t1;
693     set_float_exception_flags(0, &env->fp_status);
694     d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
695     update_fpscr(GETPC());
696 
697     return d0.ll;
698 }
699 
helper_fneg_T(uint32_t t0)700 uint32_t helper_fneg_T(uint32_t t0)
701 {
702     CPU_FloatU f;
703     f.l = t0;
704     f.f = float32_chs(f.f);
705     return f.l;
706 }
707 
helper_fsqrt_FT(uint32_t t0)708 uint32_t helper_fsqrt_FT(uint32_t t0)
709 {
710     CPU_FloatU f;
711     f.l = t0;
712     set_float_exception_flags(0, &env->fp_status);
713     f.f = float32_sqrt(f.f, &env->fp_status);
714     update_fpscr(GETPC());
715     return f.l;
716 }
717 
helper_fsqrt_DT(uint64_t t0)718 uint64_t helper_fsqrt_DT(uint64_t t0)
719 {
720     CPU_DoubleU d;
721     d.ll = t0;
722     set_float_exception_flags(0, &env->fp_status);
723     d.d = float64_sqrt(d.d, &env->fp_status);
724     update_fpscr(GETPC());
725     return d.ll;
726 }
727 
helper_fsub_FT(uint32_t t0,uint32_t t1)728 uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
729 {
730     CPU_FloatU f0, f1;
731     f0.l = t0;
732     f1.l = t1;
733     set_float_exception_flags(0, &env->fp_status);
734     f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
735     update_fpscr(GETPC());
736     return f0.l;
737 }
738 
helper_fsub_DT(uint64_t t0,uint64_t t1)739 uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
740 {
741     CPU_DoubleU d0, d1;
742 
743     d0.ll = t0;
744     d1.ll = t1;
745     set_float_exception_flags(0, &env->fp_status);
746     d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
747     update_fpscr(GETPC());
748     return d0.ll;
749 }
750 
helper_ftrc_FT(uint32_t t0)751 uint32_t helper_ftrc_FT(uint32_t t0)
752 {
753     CPU_FloatU f;
754     uint32_t ret;
755     f.l = t0;
756     set_float_exception_flags(0, &env->fp_status);
757     ret = float32_to_int32_round_to_zero(f.f, &env->fp_status);
758     update_fpscr(GETPC());
759     return ret;
760 }
761 
helper_ftrc_DT(uint64_t t0)762 uint32_t helper_ftrc_DT(uint64_t t0)
763 {
764     CPU_DoubleU d;
765     uint32_t ret;
766     d.ll = t0;
767     set_float_exception_flags(0, &env->fp_status);
768     ret = float64_to_int32_round_to_zero(d.d, &env->fp_status);
769     update_fpscr(GETPC());
770     return ret;
771 }
772 
helper_fipr(uint32_t m,uint32_t n)773 void helper_fipr(uint32_t m, uint32_t n)
774 {
775     int bank, i;
776     float32 r, p;
777 
778     bank = (env->sr & FPSCR_FR) ? 16 : 0;
779     r = float32_zero;
780     set_float_exception_flags(0, &env->fp_status);
781 
782     for (i = 0 ; i < 4 ; i++) {
783         p = float32_mul(env->fregs[bank + m + i],
784                         env->fregs[bank + n + i],
785                         &env->fp_status);
786         r = float32_add(r, p, &env->fp_status);
787     }
788     update_fpscr(GETPC());
789 
790     env->fregs[bank + n + 3] = r;
791 }
792 
helper_ftrv(uint32_t n)793 void helper_ftrv(uint32_t n)
794 {
795     int bank_matrix, bank_vector;
796     int i, j;
797     float32 r[4];
798     float32 p;
799 
800     bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
801     bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
802     set_float_exception_flags(0, &env->fp_status);
803     for (i = 0 ; i < 4 ; i++) {
804         r[i] = float32_zero;
805         for (j = 0 ; j < 4 ; j++) {
806             p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
807                             env->fregs[bank_vector + j],
808                             &env->fp_status);
809             r[i] = float32_add(r[i], p, &env->fp_status);
810         }
811     }
812     update_fpscr(GETPC());
813 
814     for (i = 0 ; i < 4 ; i++) {
815         env->fregs[bank_vector + i] = r[i];
816     }
817 }
818