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