]>
git.proxmox.com Git - qemu.git/blob - target-sh4/op_helper.c
4 * Copyright (c) 2005 Samuel Tardieu
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.
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.
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/>.
24 static void cpu_restore_state_from_retaddr(CPUSH4State
*env
, uintptr_t retaddr
)
29 tb
= tb_find_pc(retaddr
);
31 /* the PC is inside the translated code. It means that we have
32 a virtual CPU fault */
33 cpu_restore_state(tb
, env
, retaddr
);
38 #ifndef CONFIG_USER_ONLY
39 #include "softmmu_exec.h"
41 #define MMUSUFFIX _mmu
44 #include "softmmu_template.h"
47 #include "softmmu_template.h"
50 #include "softmmu_template.h"
53 #include "softmmu_template.h"
55 void tlb_fill(CPUSH4State
*env
, target_ulong addr
, int is_write
, int mmu_idx
,
60 ret
= cpu_sh4_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
);
62 /* now we have a real cpu fault */
63 cpu_restore_state_from_retaddr(env
, retaddr
);
70 void helper_ldtlb(CPUSH4State
*env
)
72 #ifdef CONFIG_USER_ONLY
74 cpu_abort(env
, "Unhandled ldtlb");
80 static inline void raise_exception(CPUSH4State
*env
, int index
,
83 env
->exception_index
= index
;
84 cpu_restore_state_from_retaddr(env
, retaddr
);
88 void helper_raise_illegal_instruction(CPUSH4State
*env
)
90 raise_exception(env
, 0x180, GETPC());
93 void helper_raise_slot_illegal_instruction(CPUSH4State
*env
)
95 raise_exception(env
, 0x1a0, GETPC());
98 void helper_raise_fpu_disable(CPUSH4State
*env
)
100 raise_exception(env
, 0x800, GETPC());
103 void helper_raise_slot_fpu_disable(CPUSH4State
*env
)
105 raise_exception(env
, 0x820, GETPC());
108 void helper_debug(CPUSH4State
*env
)
110 env
->exception_index
= EXCP_DEBUG
;
114 void helper_sleep(CPUSH4State
*env
, uint32_t next_pc
)
118 env
->exception_index
= EXCP_HLT
;
123 void helper_trapa(CPUSH4State
*env
, uint32_t tra
)
126 raise_exception(env
, 0x160, GETPC());
129 void helper_movcal(CPUSH4State
*env
, uint32_t address
, uint32_t value
)
131 if (cpu_sh4_is_cached (env
, address
))
133 memory_content
*r
= malloc (sizeof(memory_content
));
134 r
->address
= address
;
138 *(env
->movcal_backup_tail
) = r
;
139 env
->movcal_backup_tail
= &(r
->next
);
143 void helper_discard_movcal_backup(CPUSH4State
*env
)
145 memory_content
*current
= env
->movcal_backup
;
149 memory_content
*next
= current
->next
;
151 env
->movcal_backup
= current
= next
;
153 env
->movcal_backup_tail
= &(env
->movcal_backup
);
157 void helper_ocbi(CPUSH4State
*env
, uint32_t address
)
159 memory_content
**current
= &(env
->movcal_backup
);
162 uint32_t a
= (*current
)->address
;
163 if ((a
& ~0x1F) == (address
& ~0x1F))
165 memory_content
*next
= (*current
)->next
;
166 cpu_stl_data(env
, a
, (*current
)->value
);
170 env
->movcal_backup_tail
= current
;
180 uint32_t helper_addc(CPUSH4State
*env
, uint32_t arg0
, uint32_t arg1
)
186 arg1
= tmp1
+ (env
->sr
& 1);
196 uint32_t helper_addv(CPUSH4State
*env
, uint32_t arg0
, uint32_t arg1
)
198 uint32_t dest
, src
, ans
;
200 if ((int32_t) arg1
>= 0)
204 if ((int32_t) arg0
>= 0)
210 if ((int32_t) arg1
>= 0)
215 if (src
== 0 || src
== 2) {
225 #define T (env->sr & SR_T)
226 #define Q (env->sr & SR_Q ? 1 : 0)
227 #define M (env->sr & SR_M ? 1 : 0)
228 #define SETT env->sr |= SR_T
229 #define CLRT env->sr &= ~SR_T
230 #define SETQ env->sr |= SR_Q
231 #define CLRQ env->sr &= ~SR_Q
232 #define SETM env->sr |= SR_M
233 #define CLRM env->sr &= ~SR_M
235 uint32_t helper_div1(CPUSH4State
*env
, uint32_t arg0
, uint32_t arg1
)
238 uint8_t old_q
, tmp1
= 0xff;
240 //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
242 if ((0x80000000 & arg1
) != 0)
339 //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
343 void helper_macl(CPUSH4State
*env
, uint32_t arg0
, uint32_t arg1
)
347 res
= ((uint64_t) env
->mach
<< 32) | env
->macl
;
348 res
+= (int64_t) (int32_t) arg0
*(int64_t) (int32_t) arg1
;
349 env
->mach
= (res
>> 32) & 0xffffffff;
350 env
->macl
= res
& 0xffffffff;
351 if (env
->sr
& SR_S
) {
353 env
->mach
|= 0xffff0000;
355 env
->mach
&= 0x00007fff;
359 void helper_macw(CPUSH4State
*env
, uint32_t arg0
, uint32_t arg1
)
363 res
= ((uint64_t) env
->mach
<< 32) | env
->macl
;
364 res
+= (int64_t) (int16_t) arg0
*(int64_t) (int16_t) arg1
;
365 env
->mach
= (res
>> 32) & 0xffffffff;
366 env
->macl
= res
& 0xffffffff;
367 if (env
->sr
& SR_S
) {
368 if (res
< -0x80000000) {
370 env
->macl
= 0x80000000;
371 } else if (res
> 0x000000007fffffff) {
373 env
->macl
= 0x7fffffff;
378 uint32_t helper_subc(CPUSH4State
*env
, uint32_t arg0
, uint32_t arg1
)
384 arg1
= tmp1
- (env
->sr
& SR_T
);
394 uint32_t helper_subv(CPUSH4State
*env
, uint32_t arg0
, uint32_t arg1
)
396 int32_t dest
, src
, ans
;
398 if ((int32_t) arg1
>= 0)
402 if ((int32_t) arg0
>= 0)
408 if ((int32_t) arg1
>= 0)
423 static inline void set_t(CPUSH4State
*env
)
428 static inline void clr_t(CPUSH4State
*env
)
433 void helper_ld_fpscr(CPUSH4State
*env
, uint32_t val
)
435 env
->fpscr
= val
& FPSCR_MASK
;
436 if ((val
& FPSCR_RM_MASK
) == FPSCR_RM_ZERO
) {
437 set_float_rounding_mode(float_round_to_zero
, &env
->fp_status
);
439 set_float_rounding_mode(float_round_nearest_even
, &env
->fp_status
);
441 set_flush_to_zero((val
& FPSCR_DN
) != 0, &env
->fp_status
);
444 static void update_fpscr(CPUSH4State
*env
, uintptr_t retaddr
)
446 int xcpt
, cause
, enable
;
448 xcpt
= get_float_exception_flags(&env
->fp_status
);
450 /* Clear the flag entries */
451 env
->fpscr
&= ~FPSCR_FLAG_MASK
;
453 if (unlikely(xcpt
)) {
454 if (xcpt
& float_flag_invalid
) {
455 env
->fpscr
|= FPSCR_FLAG_V
;
457 if (xcpt
& float_flag_divbyzero
) {
458 env
->fpscr
|= FPSCR_FLAG_Z
;
460 if (xcpt
& float_flag_overflow
) {
461 env
->fpscr
|= FPSCR_FLAG_O
;
463 if (xcpt
& float_flag_underflow
) {
464 env
->fpscr
|= FPSCR_FLAG_U
;
466 if (xcpt
& float_flag_inexact
) {
467 env
->fpscr
|= FPSCR_FLAG_I
;
470 /* Accumulate in cause entries */
471 env
->fpscr
|= (env
->fpscr
& FPSCR_FLAG_MASK
)
472 << (FPSCR_CAUSE_SHIFT
- FPSCR_FLAG_SHIFT
);
474 /* Generate an exception if enabled */
475 cause
= (env
->fpscr
& FPSCR_CAUSE_MASK
) >> FPSCR_CAUSE_SHIFT
;
476 enable
= (env
->fpscr
& FPSCR_ENABLE_MASK
) >> FPSCR_ENABLE_SHIFT
;
477 if (cause
& enable
) {
478 cpu_restore_state_from_retaddr(env
, retaddr
);
479 env
->exception_index
= 0x120;
485 float32
helper_fabs_FT(float32 t0
)
487 return float32_abs(t0
);
490 float64
helper_fabs_DT(float64 t0
)
492 return float64_abs(t0
);
495 float32
helper_fadd_FT(CPUSH4State
*env
, float32 t0
, float32 t1
)
497 set_float_exception_flags(0, &env
->fp_status
);
498 t0
= float32_add(t0
, t1
, &env
->fp_status
);
499 update_fpscr(env
, GETPC());
503 float64
helper_fadd_DT(CPUSH4State
*env
, float64 t0
, float64 t1
)
505 set_float_exception_flags(0, &env
->fp_status
);
506 t0
= float64_add(t0
, t1
, &env
->fp_status
);
507 update_fpscr(env
, GETPC());
511 void helper_fcmp_eq_FT(CPUSH4State
*env
, float32 t0
, float32 t1
)
515 set_float_exception_flags(0, &env
->fp_status
);
516 relation
= float32_compare(t0
, t1
, &env
->fp_status
);
517 if (unlikely(relation
== float_relation_unordered
)) {
518 update_fpscr(env
, GETPC());
519 } else if (relation
== float_relation_equal
) {
526 void helper_fcmp_eq_DT(CPUSH4State
*env
, float64 t0
, float64 t1
)
530 set_float_exception_flags(0, &env
->fp_status
);
531 relation
= float64_compare(t0
, t1
, &env
->fp_status
);
532 if (unlikely(relation
== float_relation_unordered
)) {
533 update_fpscr(env
, GETPC());
534 } else if (relation
== float_relation_equal
) {
541 void helper_fcmp_gt_FT(CPUSH4State
*env
, float32 t0
, float32 t1
)
545 set_float_exception_flags(0, &env
->fp_status
);
546 relation
= float32_compare(t0
, t1
, &env
->fp_status
);
547 if (unlikely(relation
== float_relation_unordered
)) {
548 update_fpscr(env
, GETPC());
549 } else if (relation
== float_relation_greater
) {
556 void helper_fcmp_gt_DT(CPUSH4State
*env
, float64 t0
, float64 t1
)
560 set_float_exception_flags(0, &env
->fp_status
);
561 relation
= float64_compare(t0
, t1
, &env
->fp_status
);
562 if (unlikely(relation
== float_relation_unordered
)) {
563 update_fpscr(env
, GETPC());
564 } else if (relation
== float_relation_greater
) {
571 float64
helper_fcnvsd_FT_DT(CPUSH4State
*env
, float32 t0
)
574 set_float_exception_flags(0, &env
->fp_status
);
575 ret
= float32_to_float64(t0
, &env
->fp_status
);
576 update_fpscr(env
, GETPC());
580 float32
helper_fcnvds_DT_FT(CPUSH4State
*env
, float64 t0
)
583 set_float_exception_flags(0, &env
->fp_status
);
584 ret
= float64_to_float32(t0
, &env
->fp_status
);
585 update_fpscr(env
, GETPC());
589 float32
helper_fdiv_FT(CPUSH4State
*env
, float32 t0
, float32 t1
)
591 set_float_exception_flags(0, &env
->fp_status
);
592 t0
= float32_div(t0
, t1
, &env
->fp_status
);
593 update_fpscr(env
, GETPC());
597 float64
helper_fdiv_DT(CPUSH4State
*env
, float64 t0
, float64 t1
)
599 set_float_exception_flags(0, &env
->fp_status
);
600 t0
= float64_div(t0
, t1
, &env
->fp_status
);
601 update_fpscr(env
, GETPC());
605 float32
helper_float_FT(CPUSH4State
*env
, uint32_t t0
)
608 set_float_exception_flags(0, &env
->fp_status
);
609 ret
= int32_to_float32(t0
, &env
->fp_status
);
610 update_fpscr(env
, GETPC());
614 float64
helper_float_DT(CPUSH4State
*env
, uint32_t t0
)
617 set_float_exception_flags(0, &env
->fp_status
);
618 ret
= int32_to_float64(t0
, &env
->fp_status
);
619 update_fpscr(env
, GETPC());
623 float32
helper_fmac_FT(CPUSH4State
*env
, float32 t0
, float32 t1
, float32 t2
)
625 set_float_exception_flags(0, &env
->fp_status
);
626 t0
= float32_muladd(t0
, t1
, t2
, 0, &env
->fp_status
);
627 update_fpscr(env
, GETPC());
631 float32
helper_fmul_FT(CPUSH4State
*env
, float32 t0
, float32 t1
)
633 set_float_exception_flags(0, &env
->fp_status
);
634 t0
= float32_mul(t0
, t1
, &env
->fp_status
);
635 update_fpscr(env
, GETPC());
639 float64
helper_fmul_DT(CPUSH4State
*env
, float64 t0
, float64 t1
)
641 set_float_exception_flags(0, &env
->fp_status
);
642 t0
= float64_mul(t0
, t1
, &env
->fp_status
);
643 update_fpscr(env
, GETPC());
647 float32
helper_fneg_T(float32 t0
)
649 return float32_chs(t0
);
652 float32
helper_fsqrt_FT(CPUSH4State
*env
, float32 t0
)
654 set_float_exception_flags(0, &env
->fp_status
);
655 t0
= float32_sqrt(t0
, &env
->fp_status
);
656 update_fpscr(env
, GETPC());
660 float64
helper_fsqrt_DT(CPUSH4State
*env
, float64 t0
)
662 set_float_exception_flags(0, &env
->fp_status
);
663 t0
= float64_sqrt(t0
, &env
->fp_status
);
664 update_fpscr(env
, GETPC());
668 float32
helper_fsub_FT(CPUSH4State
*env
, float32 t0
, float32 t1
)
670 set_float_exception_flags(0, &env
->fp_status
);
671 t0
= float32_sub(t0
, t1
, &env
->fp_status
);
672 update_fpscr(env
, GETPC());
676 float64
helper_fsub_DT(CPUSH4State
*env
, float64 t0
, float64 t1
)
678 set_float_exception_flags(0, &env
->fp_status
);
679 t0
= float64_sub(t0
, t1
, &env
->fp_status
);
680 update_fpscr(env
, GETPC());
684 uint32_t helper_ftrc_FT(CPUSH4State
*env
, float32 t0
)
687 set_float_exception_flags(0, &env
->fp_status
);
688 ret
= float32_to_int32_round_to_zero(t0
, &env
->fp_status
);
689 update_fpscr(env
, GETPC());
693 uint32_t helper_ftrc_DT(CPUSH4State
*env
, float64 t0
)
696 set_float_exception_flags(0, &env
->fp_status
);
697 ret
= float64_to_int32_round_to_zero(t0
, &env
->fp_status
);
698 update_fpscr(env
, GETPC());
702 void helper_fipr(CPUSH4State
*env
, uint32_t m
, uint32_t n
)
707 bank
= (env
->sr
& FPSCR_FR
) ? 16 : 0;
709 set_float_exception_flags(0, &env
->fp_status
);
711 for (i
= 0 ; i
< 4 ; i
++) {
712 p
= float32_mul(env
->fregs
[bank
+ m
+ i
],
713 env
->fregs
[bank
+ n
+ i
],
715 r
= float32_add(r
, p
, &env
->fp_status
);
717 update_fpscr(env
, GETPC());
719 env
->fregs
[bank
+ n
+ 3] = r
;
722 void helper_ftrv(CPUSH4State
*env
, uint32_t n
)
724 int bank_matrix
, bank_vector
;
729 bank_matrix
= (env
->sr
& FPSCR_FR
) ? 0 : 16;
730 bank_vector
= (env
->sr
& FPSCR_FR
) ? 16 : 0;
731 set_float_exception_flags(0, &env
->fp_status
);
732 for (i
= 0 ; i
< 4 ; i
++) {
734 for (j
= 0 ; j
< 4 ; j
++) {
735 p
= float32_mul(env
->fregs
[bank_matrix
+ 4 * j
+ i
],
736 env
->fregs
[bank_vector
+ j
],
738 r
[i
] = float32_add(r
[i
], p
, &env
->fp_status
);
741 update_fpscr(env
, GETPC());
743 for (i
= 0 ; i
< 4 ; i
++) {
744 env
->fregs
[bank_vector
+ i
] = r
[i
];