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/>.
22 #include "dyngen-exec.h"
25 static void cpu_restore_state_from_retaddr(void *retaddr
)
31 pc
= (unsigned long) retaddr
;
34 /* the PC is inside the translated code. It means that we have
35 a virtual CPU fault */
36 cpu_restore_state(tb
, env
, pc
);
41 #ifndef CONFIG_USER_ONLY
42 #include "softmmu_exec.h"
44 #define MMUSUFFIX _mmu
47 #include "softmmu_template.h"
50 #include "softmmu_template.h"
53 #include "softmmu_template.h"
56 #include "softmmu_template.h"
58 void tlb_fill(CPUState
*env1
, target_ulong addr
, int is_write
, int mmu_idx
,
66 ret
= cpu_sh4_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
);
68 /* now we have a real cpu fault */
69 cpu_restore_state_from_retaddr(retaddr
);
77 void helper_ldtlb(void)
79 #ifdef CONFIG_USER_ONLY
81 cpu_abort(env
, "Unhandled ldtlb");
87 static inline void raise_exception(int index
, void *retaddr
)
89 env
->exception_index
= index
;
90 cpu_restore_state_from_retaddr(retaddr
);
94 void helper_raise_illegal_instruction(void)
96 raise_exception(0x180, GETPC());
99 void helper_raise_slot_illegal_instruction(void)
101 raise_exception(0x1a0, GETPC());
104 void helper_raise_fpu_disable(void)
106 raise_exception(0x800, GETPC());
109 void helper_raise_slot_fpu_disable(void)
111 raise_exception(0x820, GETPC());
114 void helper_debug(void)
116 env
->exception_index
= EXCP_DEBUG
;
120 void helper_sleep(uint32_t next_pc
)
124 env
->exception_index
= EXCP_HLT
;
129 void helper_trapa(uint32_t tra
)
132 raise_exception(0x160, GETPC());
135 void helper_movcal(uint32_t address
, uint32_t value
)
137 if (cpu_sh4_is_cached (env
, address
))
139 memory_content
*r
= malloc (sizeof(memory_content
));
140 r
->address
= address
;
144 *(env
->movcal_backup_tail
) = r
;
145 env
->movcal_backup_tail
= &(r
->next
);
149 void helper_discard_movcal_backup(void)
151 memory_content
*current
= env
->movcal_backup
;
155 memory_content
*next
= current
->next
;
157 env
->movcal_backup
= current
= next
;
159 env
->movcal_backup_tail
= &(env
->movcal_backup
);
163 void helper_ocbi(uint32_t address
)
165 memory_content
**current
= &(env
->movcal_backup
);
168 uint32_t a
= (*current
)->address
;
169 if ((a
& ~0x1F) == (address
& ~0x1F))
171 memory_content
*next
= (*current
)->next
;
172 stl(a
, (*current
)->value
);
176 env
->movcal_backup_tail
= current
;
186 uint32_t helper_addc(uint32_t arg0
, uint32_t arg1
)
192 arg1
= tmp1
+ (env
->sr
& 1);
202 uint32_t helper_addv(uint32_t arg0
, uint32_t arg1
)
204 uint32_t dest
, src
, ans
;
206 if ((int32_t) arg1
>= 0)
210 if ((int32_t) arg0
>= 0)
216 if ((int32_t) arg1
>= 0)
221 if (src
== 0 || src
== 2) {
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
241 uint32_t helper_div1(uint32_t arg0
, uint32_t arg1
)
244 uint8_t old_q
, tmp1
= 0xff;
246 //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
248 if ((0x80000000 & arg1
) != 0)
345 //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
349 void helper_macl(uint32_t arg0
, uint32_t arg1
)
353 res
= ((uint64_t) env
->mach
<< 32) | env
->macl
;
354 res
+= (int64_t) (int32_t) arg0
*(int64_t) (int32_t) arg1
;
355 env
->mach
= (res
>> 32) & 0xffffffff;
356 env
->macl
= res
& 0xffffffff;
357 if (env
->sr
& SR_S
) {
359 env
->mach
|= 0xffff0000;
361 env
->mach
&= 0x00007fff;
365 void helper_macw(uint32_t arg0
, uint32_t arg1
)
369 res
= ((uint64_t) env
->mach
<< 32) | env
->macl
;
370 res
+= (int64_t) (int16_t) arg0
*(int64_t) (int16_t) arg1
;
371 env
->mach
= (res
>> 32) & 0xffffffff;
372 env
->macl
= res
& 0xffffffff;
373 if (env
->sr
& SR_S
) {
374 if (res
< -0x80000000) {
376 env
->macl
= 0x80000000;
377 } else if (res
> 0x000000007fffffff) {
379 env
->macl
= 0x7fffffff;
384 uint32_t helper_subc(uint32_t arg0
, uint32_t arg1
)
390 arg1
= tmp1
- (env
->sr
& SR_T
);
400 uint32_t helper_subv(uint32_t arg0
, uint32_t arg1
)
402 int32_t dest
, src
, ans
;
404 if ((int32_t) arg1
>= 0)
408 if ((int32_t) arg0
>= 0)
414 if ((int32_t) arg1
>= 0)
429 static inline void set_t(void)
434 static inline void clr_t(void)
439 void helper_ld_fpscr(uint32_t val
)
441 env
->fpscr
= val
& FPSCR_MASK
;
442 if ((val
& FPSCR_RM_MASK
) == FPSCR_RM_ZERO
) {
443 set_float_rounding_mode(float_round_to_zero
, &env
->fp_status
);
445 set_float_rounding_mode(float_round_nearest_even
, &env
->fp_status
);
447 set_flush_to_zero((val
& FPSCR_DN
) != 0, &env
->fp_status
);
450 static void update_fpscr(void *retaddr
)
452 int xcpt
, cause
, enable
;
454 xcpt
= get_float_exception_flags(&env
->fp_status
);
456 /* Clear the flag entries */
457 env
->fpscr
&= ~FPSCR_FLAG_MASK
;
459 if (unlikely(xcpt
)) {
460 if (xcpt
& float_flag_invalid
) {
461 env
->fpscr
|= FPSCR_FLAG_V
;
463 if (xcpt
& float_flag_divbyzero
) {
464 env
->fpscr
|= FPSCR_FLAG_Z
;
466 if (xcpt
& float_flag_overflow
) {
467 env
->fpscr
|= FPSCR_FLAG_O
;
469 if (xcpt
& float_flag_underflow
) {
470 env
->fpscr
|= FPSCR_FLAG_U
;
472 if (xcpt
& float_flag_inexact
) {
473 env
->fpscr
|= FPSCR_FLAG_I
;
476 /* Accumulate in cause entries */
477 env
->fpscr
|= (env
->fpscr
& FPSCR_FLAG_MASK
)
478 << (FPSCR_CAUSE_SHIFT
- FPSCR_FLAG_SHIFT
);
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;
491 float32
helper_fabs_FT(float32 t0
)
493 return float32_abs(t0
);
496 float64
helper_fabs_DT(float64 t0
)
498 return float64_abs(t0
);
501 float32
helper_fadd_FT(float32 t0
, float32 t1
)
503 set_float_exception_flags(0, &env
->fp_status
);
504 t0
= float32_add(t0
, t1
, &env
->fp_status
);
505 update_fpscr(GETPC());
509 float64
helper_fadd_DT(float64 t0
, float64 t1
)
511 set_float_exception_flags(0, &env
->fp_status
);
512 t0
= float64_add(t0
, t1
, &env
->fp_status
);
513 update_fpscr(GETPC());
517 void helper_fcmp_eq_FT(float32 t0
, float32 t1
)
521 set_float_exception_flags(0, &env
->fp_status
);
522 relation
= float32_compare(t0
, t1
, &env
->fp_status
);
523 if (unlikely(relation
== float_relation_unordered
)) {
524 update_fpscr(GETPC());
525 } else if (relation
== float_relation_equal
) {
532 void helper_fcmp_eq_DT(float64 t0
, float64 t1
)
536 set_float_exception_flags(0, &env
->fp_status
);
537 relation
= float64_compare(t0
, t1
, &env
->fp_status
);
538 if (unlikely(relation
== float_relation_unordered
)) {
539 update_fpscr(GETPC());
540 } else if (relation
== float_relation_equal
) {
547 void helper_fcmp_gt_FT(float32 t0
, float32 t1
)
551 set_float_exception_flags(0, &env
->fp_status
);
552 relation
= float32_compare(t0
, t1
, &env
->fp_status
);
553 if (unlikely(relation
== float_relation_unordered
)) {
554 update_fpscr(GETPC());
555 } else if (relation
== float_relation_greater
) {
562 void helper_fcmp_gt_DT(float64 t0
, float64 t1
)
566 set_float_exception_flags(0, &env
->fp_status
);
567 relation
= float64_compare(t0
, t1
, &env
->fp_status
);
568 if (unlikely(relation
== float_relation_unordered
)) {
569 update_fpscr(GETPC());
570 } else if (relation
== float_relation_greater
) {
577 float64
helper_fcnvsd_FT_DT(float32 t0
)
580 set_float_exception_flags(0, &env
->fp_status
);
581 ret
= float32_to_float64(t0
, &env
->fp_status
);
582 update_fpscr(GETPC());
586 float32
helper_fcnvds_DT_FT(float64 t0
)
589 set_float_exception_flags(0, &env
->fp_status
);
590 ret
= float64_to_float32(t0
, &env
->fp_status
);
591 update_fpscr(GETPC());
595 float32
helper_fdiv_FT(float32 t0
, float32 t1
)
597 set_float_exception_flags(0, &env
->fp_status
);
598 t0
= float32_div(t0
, t1
, &env
->fp_status
);
599 update_fpscr(GETPC());
603 float64
helper_fdiv_DT(float64 t0
, float64 t1
)
605 set_float_exception_flags(0, &env
->fp_status
);
606 t0
= float64_div(t0
, t1
, &env
->fp_status
);
607 update_fpscr(GETPC());
611 float32
helper_float_FT(uint32_t t0
)
614 set_float_exception_flags(0, &env
->fp_status
);
615 ret
= int32_to_float32(t0
, &env
->fp_status
);
616 update_fpscr(GETPC());
620 float64
helper_float_DT(uint32_t t0
)
623 set_float_exception_flags(0, &env
->fp_status
);
624 ret
= int32_to_float64(t0
, &env
->fp_status
);
625 update_fpscr(GETPC());
629 float32
helper_fmac_FT(float32 t0
, float32 t1
, float32 t2
)
631 set_float_exception_flags(0, &env
->fp_status
);
632 t0
= float32_mul(t0
, t1
, &env
->fp_status
);
633 t0
= float32_add(t0
, t2
, &env
->fp_status
);
634 update_fpscr(GETPC());
638 float32
helper_fmul_FT(float32 t0
, float32 t1
)
640 set_float_exception_flags(0, &env
->fp_status
);
641 t0
= float32_mul(t0
, t1
, &env
->fp_status
);
642 update_fpscr(GETPC());
646 float64
helper_fmul_DT(float64 t0
, float64 t1
)
648 set_float_exception_flags(0, &env
->fp_status
);
649 t0
= float64_mul(t0
, t1
, &env
->fp_status
);
650 update_fpscr(GETPC());
654 float32
helper_fneg_T(float32 t0
)
656 return float32_chs(t0
);
659 float32
helper_fsqrt_FT(float32 t0
)
661 set_float_exception_flags(0, &env
->fp_status
);
662 t0
= float32_sqrt(t0
, &env
->fp_status
);
663 update_fpscr(GETPC());
667 float64
helper_fsqrt_DT(float64 t0
)
669 set_float_exception_flags(0, &env
->fp_status
);
670 t0
= float64_sqrt(t0
, &env
->fp_status
);
671 update_fpscr(GETPC());
675 float32
helper_fsub_FT(float32 t0
, float32 t1
)
677 set_float_exception_flags(0, &env
->fp_status
);
678 t0
= float32_sub(t0
, t1
, &env
->fp_status
);
679 update_fpscr(GETPC());
683 float64
helper_fsub_DT(float64 t0
, float64 t1
)
685 set_float_exception_flags(0, &env
->fp_status
);
686 t0
= float64_sub(t0
, t1
, &env
->fp_status
);
687 update_fpscr(GETPC());
691 uint32_t helper_ftrc_FT(float32 t0
)
694 set_float_exception_flags(0, &env
->fp_status
);
695 ret
= float32_to_int32_round_to_zero(t0
, &env
->fp_status
);
696 update_fpscr(GETPC());
700 uint32_t helper_ftrc_DT(float64 t0
)
703 set_float_exception_flags(0, &env
->fp_status
);
704 ret
= float64_to_int32_round_to_zero(t0
, &env
->fp_status
);
705 update_fpscr(GETPC());
709 void helper_fipr(uint32_t m
, uint32_t n
)
714 bank
= (env
->sr
& FPSCR_FR
) ? 16 : 0;
716 set_float_exception_flags(0, &env
->fp_status
);
718 for (i
= 0 ; i
< 4 ; i
++) {
719 p
= float32_mul(env
->fregs
[bank
+ m
+ i
],
720 env
->fregs
[bank
+ n
+ i
],
722 r
= float32_add(r
, p
, &env
->fp_status
);
724 update_fpscr(GETPC());
726 env
->fregs
[bank
+ n
+ 3] = r
;
729 void helper_ftrv(uint32_t n
)
731 int bank_matrix
, bank_vector
;
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
++) {
741 for (j
= 0 ; j
< 4 ; j
++) {
742 p
= float32_mul(env
->fregs
[bank_matrix
+ 4 * j
+ i
],
743 env
->fregs
[bank_vector
+ j
],
745 r
[i
] = float32_add(r
[i
], p
, &env
->fp_status
);
748 update_fpscr(GETPC());
750 for (i
= 0 ; i
< 4 ; i
++) {
751 env
->fregs
[bank_vector
+ i
] = r
[i
];