1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth * SH4 emulation
3fcf5ef2aSThomas Huth *
4fcf5ef2aSThomas Huth * Copyright (c) 2005 Samuel Tardieu
5fcf5ef2aSThomas Huth *
6fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or
7fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public
8fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either
96faf2b6cSThomas Huth * version 2.1 of the License, or (at your option) any later version.
10fcf5ef2aSThomas Huth *
11fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful,
12fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of
13fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14fcf5ef2aSThomas Huth * Lesser General Public License for more details.
15fcf5ef2aSThomas Huth *
16fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public
17fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18fcf5ef2aSThomas Huth */
19fcf5ef2aSThomas Huth #include "qemu/osdep.h"
20fcf5ef2aSThomas Huth #include "cpu.h"
21fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
22fcf5ef2aSThomas Huth #include "exec/exec-all.h"
23fcf5ef2aSThomas Huth #include "exec/cpu_ldst.h"
2424f91e81SAlex Bennée #include "fpu/softfloat.h"
25fcf5ef2aSThomas Huth
26fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
27fcf5ef2aSThomas Huth
superh_cpu_do_unaligned_access(CPUState * cs,vaddr addr,MMUAccessType access_type,int mmu_idx,uintptr_t retaddr)2834257c21SAurelien Jarno void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
2934257c21SAurelien Jarno MMUAccessType access_type,
3034257c21SAurelien Jarno int mmu_idx, uintptr_t retaddr)
3134257c21SAurelien Jarno {
3294956d7bSPhilippe Mathieu-Daudé cpu_env(cs)->tea = addr;
3334257c21SAurelien Jarno switch (access_type) {
3434257c21SAurelien Jarno case MMU_INST_FETCH:
3534257c21SAurelien Jarno case MMU_DATA_LOAD:
3634257c21SAurelien Jarno cs->exception_index = 0x0e0;
3734257c21SAurelien Jarno break;
3834257c21SAurelien Jarno case MMU_DATA_STORE:
3934257c21SAurelien Jarno cs->exception_index = 0x100;
4034257c21SAurelien Jarno break;
410ee0942aSRichard Henderson default:
420ee0942aSRichard Henderson g_assert_not_reached();
4334257c21SAurelien Jarno }
4434257c21SAurelien Jarno cpu_loop_exit_restore(cs, retaddr);
4534257c21SAurelien Jarno }
4634257c21SAurelien Jarno
47fcf5ef2aSThomas Huth #endif
48fcf5ef2aSThomas Huth
helper_ldtlb(CPUSH4State * env)49fcf5ef2aSThomas Huth void helper_ldtlb(CPUSH4State *env)
50fcf5ef2aSThomas Huth {
51fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY
52dad1c8ecSRichard Henderson cpu_abort(env_cpu(env), "Unhandled ldtlb");
53fcf5ef2aSThomas Huth #else
54fcf5ef2aSThomas Huth cpu_load_tlb(env);
55fcf5ef2aSThomas Huth #endif
56fcf5ef2aSThomas Huth }
57fcf5ef2aSThomas Huth
588905770bSMarc-André Lureau static inline G_NORETURN
raise_exception(CPUSH4State * env,int index,uintptr_t retaddr)598905770bSMarc-André Lureau void raise_exception(CPUSH4State *env, int index,
60fcf5ef2aSThomas Huth uintptr_t retaddr)
61fcf5ef2aSThomas Huth {
62dad1c8ecSRichard Henderson CPUState *cs = env_cpu(env);
63fcf5ef2aSThomas Huth
64fcf5ef2aSThomas Huth cs->exception_index = index;
6557e2d417SAurelien Jarno cpu_loop_exit_restore(cs, retaddr);
66fcf5ef2aSThomas Huth }
67fcf5ef2aSThomas Huth
helper_raise_illegal_instruction(CPUSH4State * env)68fcf5ef2aSThomas Huth void helper_raise_illegal_instruction(CPUSH4State *env)
69fcf5ef2aSThomas Huth {
70fcf5ef2aSThomas Huth raise_exception(env, 0x180, 0);
71fcf5ef2aSThomas Huth }
72fcf5ef2aSThomas Huth
helper_raise_slot_illegal_instruction(CPUSH4State * env)73fcf5ef2aSThomas Huth void helper_raise_slot_illegal_instruction(CPUSH4State *env)
74fcf5ef2aSThomas Huth {
75fcf5ef2aSThomas Huth raise_exception(env, 0x1a0, 0);
76fcf5ef2aSThomas Huth }
77fcf5ef2aSThomas Huth
helper_raise_fpu_disable(CPUSH4State * env)78fcf5ef2aSThomas Huth void helper_raise_fpu_disable(CPUSH4State *env)
79fcf5ef2aSThomas Huth {
80fcf5ef2aSThomas Huth raise_exception(env, 0x800, 0);
81fcf5ef2aSThomas Huth }
82fcf5ef2aSThomas Huth
helper_raise_slot_fpu_disable(CPUSH4State * env)83fcf5ef2aSThomas Huth void helper_raise_slot_fpu_disable(CPUSH4State *env)
84fcf5ef2aSThomas Huth {
85fcf5ef2aSThomas Huth raise_exception(env, 0x820, 0);
86fcf5ef2aSThomas Huth }
87fcf5ef2aSThomas Huth
helper_sleep(CPUSH4State * env)88fcf5ef2aSThomas Huth void helper_sleep(CPUSH4State *env)
89fcf5ef2aSThomas Huth {
90dad1c8ecSRichard Henderson CPUState *cs = env_cpu(env);
91fcf5ef2aSThomas Huth
92fcf5ef2aSThomas Huth cs->halted = 1;
93fcf5ef2aSThomas Huth env->in_sleep = 1;
94fcf5ef2aSThomas Huth raise_exception(env, EXCP_HLT, 0);
95fcf5ef2aSThomas Huth }
96fcf5ef2aSThomas Huth
helper_trapa(CPUSH4State * env,uint32_t tra)97fcf5ef2aSThomas Huth void helper_trapa(CPUSH4State *env, uint32_t tra)
98fcf5ef2aSThomas Huth {
99fcf5ef2aSThomas Huth env->tra = tra << 2;
100fcf5ef2aSThomas Huth raise_exception(env, 0x160, 0);
101fcf5ef2aSThomas Huth }
102fcf5ef2aSThomas Huth
helper_exclusive(CPUSH4State * env)1034bfa602bSRichard Henderson void helper_exclusive(CPUSH4State *env)
1044bfa602bSRichard Henderson {
1054bfa602bSRichard Henderson /* We do not want cpu_restore_state to run. */
10629a0af61SRichard Henderson cpu_loop_exit_atomic(env_cpu(env), 0);
1074bfa602bSRichard Henderson }
1084bfa602bSRichard Henderson
helper_movcal(CPUSH4State * env,uint32_t address,uint32_t value)109fcf5ef2aSThomas Huth void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value)
110fcf5ef2aSThomas Huth {
111fcf5ef2aSThomas Huth if (cpu_sh4_is_cached (env, address))
112fcf5ef2aSThomas Huth {
113fcf5ef2aSThomas Huth memory_content *r = g_new(memory_content, 1);
114fcf5ef2aSThomas Huth
115fcf5ef2aSThomas Huth r->address = address;
116fcf5ef2aSThomas Huth r->value = value;
117fcf5ef2aSThomas Huth r->next = NULL;
118fcf5ef2aSThomas Huth
119fcf5ef2aSThomas Huth *(env->movcal_backup_tail) = r;
120fcf5ef2aSThomas Huth env->movcal_backup_tail = &(r->next);
121fcf5ef2aSThomas Huth }
122fcf5ef2aSThomas Huth }
123fcf5ef2aSThomas Huth
helper_discard_movcal_backup(CPUSH4State * env)124fcf5ef2aSThomas Huth void helper_discard_movcal_backup(CPUSH4State *env)
125fcf5ef2aSThomas Huth {
126fcf5ef2aSThomas Huth memory_content *current = env->movcal_backup;
127fcf5ef2aSThomas Huth
128fcf5ef2aSThomas Huth while(current)
129fcf5ef2aSThomas Huth {
130fcf5ef2aSThomas Huth memory_content *next = current->next;
131fcf5ef2aSThomas Huth g_free(current);
132fcf5ef2aSThomas Huth env->movcal_backup = current = next;
133fcf5ef2aSThomas Huth if (current == NULL)
134fcf5ef2aSThomas Huth env->movcal_backup_tail = &(env->movcal_backup);
135fcf5ef2aSThomas Huth }
136fcf5ef2aSThomas Huth }
137fcf5ef2aSThomas Huth
helper_ocbi(CPUSH4State * env,uint32_t address)138fcf5ef2aSThomas Huth void helper_ocbi(CPUSH4State *env, uint32_t address)
139fcf5ef2aSThomas Huth {
140fcf5ef2aSThomas Huth memory_content **current = &(env->movcal_backup);
141fcf5ef2aSThomas Huth while (*current)
142fcf5ef2aSThomas Huth {
143fcf5ef2aSThomas Huth uint32_t a = (*current)->address;
144fcf5ef2aSThomas Huth if ((a & ~0x1F) == (address & ~0x1F))
145fcf5ef2aSThomas Huth {
146fcf5ef2aSThomas Huth memory_content *next = (*current)->next;
147fcf5ef2aSThomas Huth cpu_stl_data(env, a, (*current)->value);
148fcf5ef2aSThomas Huth
149fcf5ef2aSThomas Huth if (next == NULL)
150fcf5ef2aSThomas Huth {
151fcf5ef2aSThomas Huth env->movcal_backup_tail = current;
152fcf5ef2aSThomas Huth }
153fcf5ef2aSThomas Huth
154fcf5ef2aSThomas Huth g_free(*current);
155fcf5ef2aSThomas Huth *current = next;
156fcf5ef2aSThomas Huth break;
157fcf5ef2aSThomas Huth }
158fcf5ef2aSThomas Huth }
159fcf5ef2aSThomas Huth }
160fcf5ef2aSThomas Huth
helper_macl(CPUSH4State * env,int32_t arg0,int32_t arg1)161c97e8977SZack Buhman void helper_macl(CPUSH4State *env, int32_t arg0, int32_t arg1)
162fcf5ef2aSThomas Huth {
163c97e8977SZack Buhman const int64_t min = -(1ll << 47);
164c97e8977SZack Buhman const int64_t max = (1ll << 47) - 1;
165c97e8977SZack Buhman int64_t mul = (int64_t)arg0 * arg1;
166c97e8977SZack Buhman int64_t mac = env->mac;
167fcf5ef2aSThomas Huth int64_t res;
168fcf5ef2aSThomas Huth
169c97e8977SZack Buhman if (!(env->sr & (1u << SR_S))) {
170c97e8977SZack Buhman res = mac + mul;
171c97e8977SZack Buhman } else if (sadd64_overflow(mac, mul, &res)) {
172c97e8977SZack Buhman res = mac < 0 ? min : max;
173c97e8977SZack Buhman } else {
174c97e8977SZack Buhman res = MIN(MAX(res, min), max);
175fcf5ef2aSThomas Huth }
176c97e8977SZack Buhman
177c97e8977SZack Buhman env->mac = res;
178fcf5ef2aSThomas Huth }
179fcf5ef2aSThomas Huth
helper_macw(CPUSH4State * env,int32_t arg0,int32_t arg1)180*7227c0cdSZack Buhman void helper_macw(CPUSH4State *env, int32_t arg0, int32_t arg1)
181fcf5ef2aSThomas Huth {
182*7227c0cdSZack Buhman /* Inputs are already sign-extended from 16 bits. */
183*7227c0cdSZack Buhman int32_t mul = arg0 * arg1;
184fcf5ef2aSThomas Huth
185fcf5ef2aSThomas Huth if (env->sr & (1u << SR_S)) {
186*7227c0cdSZack Buhman /*
187*7227c0cdSZack Buhman * In saturation arithmetic mode, the accumulator is 32-bit
188*7227c0cdSZack Buhman * with carry. MACH is not considered during the addition
189*7227c0cdSZack Buhman * operation nor the 32-bit saturation logic.
190*7227c0cdSZack Buhman */
191*7227c0cdSZack Buhman int32_t res, macl = env->macl;
192*7227c0cdSZack Buhman
193*7227c0cdSZack Buhman if (sadd32_overflow(macl, mul, &res)) {
194*7227c0cdSZack Buhman res = macl < 0 ? INT32_MIN : INT32_MAX;
195*7227c0cdSZack Buhman /* If overflow occurs, the MACH register is set to 1. */
196fcf5ef2aSThomas Huth env->mach = 1;
197fcf5ef2aSThomas Huth }
198*7227c0cdSZack Buhman env->macl = res;
199*7227c0cdSZack Buhman } else {
200*7227c0cdSZack Buhman /* In non-saturation arithmetic mode, the accumulator is 64-bit */
201*7227c0cdSZack Buhman env->mac += mul;
202fcf5ef2aSThomas Huth }
203fcf5ef2aSThomas Huth }
204fcf5ef2aSThomas Huth
helper_ld_fpscr(CPUSH4State * env,uint32_t val)205fcf5ef2aSThomas Huth void helper_ld_fpscr(CPUSH4State *env, uint32_t val)
206fcf5ef2aSThomas Huth {
207fcf5ef2aSThomas Huth env->fpscr = val & FPSCR_MASK;
208fcf5ef2aSThomas Huth if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
209fcf5ef2aSThomas Huth set_float_rounding_mode(float_round_to_zero, &env->fp_status);
210fcf5ef2aSThomas Huth } else {
211fcf5ef2aSThomas Huth set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
212fcf5ef2aSThomas Huth }
213fcf5ef2aSThomas Huth set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
214fcf5ef2aSThomas Huth }
215fcf5ef2aSThomas Huth
update_fpscr(CPUSH4State * env,uintptr_t retaddr)216fcf5ef2aSThomas Huth static void update_fpscr(CPUSH4State *env, uintptr_t retaddr)
217fcf5ef2aSThomas Huth {
218fcf5ef2aSThomas Huth int xcpt, cause, enable;
219fcf5ef2aSThomas Huth
220fcf5ef2aSThomas Huth xcpt = get_float_exception_flags(&env->fp_status);
221fcf5ef2aSThomas Huth
222801f4dacSAurelien Jarno /* Clear the cause entries */
223801f4dacSAurelien Jarno env->fpscr &= ~FPSCR_CAUSE_MASK;
224fcf5ef2aSThomas Huth
225fcf5ef2aSThomas Huth if (unlikely(xcpt)) {
226fcf5ef2aSThomas Huth if (xcpt & float_flag_invalid) {
227801f4dacSAurelien Jarno env->fpscr |= FPSCR_CAUSE_V;
228fcf5ef2aSThomas Huth }
229fcf5ef2aSThomas Huth if (xcpt & float_flag_divbyzero) {
230801f4dacSAurelien Jarno env->fpscr |= FPSCR_CAUSE_Z;
231fcf5ef2aSThomas Huth }
232fcf5ef2aSThomas Huth if (xcpt & float_flag_overflow) {
233801f4dacSAurelien Jarno env->fpscr |= FPSCR_CAUSE_O;
234fcf5ef2aSThomas Huth }
235fcf5ef2aSThomas Huth if (xcpt & float_flag_underflow) {
236801f4dacSAurelien Jarno env->fpscr |= FPSCR_CAUSE_U;
237fcf5ef2aSThomas Huth }
238fcf5ef2aSThomas Huth if (xcpt & float_flag_inexact) {
239801f4dacSAurelien Jarno env->fpscr |= FPSCR_CAUSE_I;
240fcf5ef2aSThomas Huth }
241fcf5ef2aSThomas Huth
242801f4dacSAurelien Jarno /* Accumulate in flag entries */
243801f4dacSAurelien Jarno env->fpscr |= (env->fpscr & FPSCR_CAUSE_MASK)
244801f4dacSAurelien Jarno >> (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT);
245fcf5ef2aSThomas Huth
246fcf5ef2aSThomas Huth /* Generate an exception if enabled */
247fcf5ef2aSThomas Huth cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
248fcf5ef2aSThomas Huth enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
249fcf5ef2aSThomas Huth if (cause & enable) {
250fcf5ef2aSThomas Huth raise_exception(env, 0x120, retaddr);
251fcf5ef2aSThomas Huth }
252fcf5ef2aSThomas Huth }
253fcf5ef2aSThomas Huth }
254fcf5ef2aSThomas Huth
helper_fadd_FT(CPUSH4State * env,float32 t0,float32 t1)255fcf5ef2aSThomas Huth float32 helper_fadd_FT(CPUSH4State *env, float32 t0, float32 t1)
256fcf5ef2aSThomas Huth {
257fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
258fcf5ef2aSThomas Huth t0 = float32_add(t0, t1, &env->fp_status);
259fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
260fcf5ef2aSThomas Huth return t0;
261fcf5ef2aSThomas Huth }
262fcf5ef2aSThomas Huth
helper_fadd_DT(CPUSH4State * env,float64 t0,float64 t1)263fcf5ef2aSThomas Huth float64 helper_fadd_DT(CPUSH4State *env, float64 t0, float64 t1)
264fcf5ef2aSThomas Huth {
265fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
266fcf5ef2aSThomas Huth t0 = float64_add(t0, t1, &env->fp_status);
267fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
268fcf5ef2aSThomas Huth return t0;
269fcf5ef2aSThomas Huth }
270fcf5ef2aSThomas Huth
helper_fcmp_eq_FT(CPUSH4State * env,float32 t0,float32 t1)27192f1f83eSAurelien Jarno uint32_t helper_fcmp_eq_FT(CPUSH4State *env, float32 t0, float32 t1)
272fcf5ef2aSThomas Huth {
273fcf5ef2aSThomas Huth int relation;
274fcf5ef2aSThomas Huth
275fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
276fcf5ef2aSThomas Huth relation = float32_compare(t0, t1, &env->fp_status);
277fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
27892f1f83eSAurelien Jarno return relation == float_relation_equal;
279fcf5ef2aSThomas Huth }
280fcf5ef2aSThomas Huth
helper_fcmp_eq_DT(CPUSH4State * env,float64 t0,float64 t1)28192f1f83eSAurelien Jarno uint32_t helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1)
282fcf5ef2aSThomas Huth {
283fcf5ef2aSThomas Huth int relation;
284fcf5ef2aSThomas Huth
285fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
286fcf5ef2aSThomas Huth relation = float64_compare(t0, t1, &env->fp_status);
287fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
28892f1f83eSAurelien Jarno return relation == float_relation_equal;
289fcf5ef2aSThomas Huth }
290fcf5ef2aSThomas Huth
helper_fcmp_gt_FT(CPUSH4State * env,float32 t0,float32 t1)29192f1f83eSAurelien Jarno uint32_t helper_fcmp_gt_FT(CPUSH4State *env, float32 t0, float32 t1)
292fcf5ef2aSThomas Huth {
293fcf5ef2aSThomas Huth int relation;
294fcf5ef2aSThomas Huth
295fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
296fcf5ef2aSThomas Huth relation = float32_compare(t0, t1, &env->fp_status);
297fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
29892f1f83eSAurelien Jarno return relation == float_relation_greater;
299fcf5ef2aSThomas Huth }
300fcf5ef2aSThomas Huth
helper_fcmp_gt_DT(CPUSH4State * env,float64 t0,float64 t1)30192f1f83eSAurelien Jarno uint32_t helper_fcmp_gt_DT(CPUSH4State *env, float64 t0, float64 t1)
302fcf5ef2aSThomas Huth {
303fcf5ef2aSThomas Huth int relation;
304fcf5ef2aSThomas Huth
305fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
306fcf5ef2aSThomas Huth relation = float64_compare(t0, t1, &env->fp_status);
307fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
30892f1f83eSAurelien Jarno return relation == float_relation_greater;
309fcf5ef2aSThomas Huth }
310fcf5ef2aSThomas Huth
helper_fcnvsd_FT_DT(CPUSH4State * env,float32 t0)311fcf5ef2aSThomas Huth float64 helper_fcnvsd_FT_DT(CPUSH4State *env, float32 t0)
312fcf5ef2aSThomas Huth {
313fcf5ef2aSThomas Huth float64 ret;
314fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
315fcf5ef2aSThomas Huth ret = float32_to_float64(t0, &env->fp_status);
316fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
317fcf5ef2aSThomas Huth return ret;
318fcf5ef2aSThomas Huth }
319fcf5ef2aSThomas Huth
helper_fcnvds_DT_FT(CPUSH4State * env,float64 t0)320fcf5ef2aSThomas Huth float32 helper_fcnvds_DT_FT(CPUSH4State *env, float64 t0)
321fcf5ef2aSThomas Huth {
322fcf5ef2aSThomas Huth float32 ret;
323fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
324fcf5ef2aSThomas Huth ret = float64_to_float32(t0, &env->fp_status);
325fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
326fcf5ef2aSThomas Huth return ret;
327fcf5ef2aSThomas Huth }
328fcf5ef2aSThomas Huth
helper_fdiv_FT(CPUSH4State * env,float32 t0,float32 t1)329fcf5ef2aSThomas Huth float32 helper_fdiv_FT(CPUSH4State *env, float32 t0, float32 t1)
330fcf5ef2aSThomas Huth {
331fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
332fcf5ef2aSThomas Huth t0 = float32_div(t0, t1, &env->fp_status);
333fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
334fcf5ef2aSThomas Huth return t0;
335fcf5ef2aSThomas Huth }
336fcf5ef2aSThomas Huth
helper_fdiv_DT(CPUSH4State * env,float64 t0,float64 t1)337fcf5ef2aSThomas Huth float64 helper_fdiv_DT(CPUSH4State *env, float64 t0, float64 t1)
338fcf5ef2aSThomas Huth {
339fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
340fcf5ef2aSThomas Huth t0 = float64_div(t0, t1, &env->fp_status);
341fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
342fcf5ef2aSThomas Huth return t0;
343fcf5ef2aSThomas Huth }
344fcf5ef2aSThomas Huth
helper_float_FT(CPUSH4State * env,uint32_t t0)345fcf5ef2aSThomas Huth float32 helper_float_FT(CPUSH4State *env, uint32_t t0)
346fcf5ef2aSThomas Huth {
347fcf5ef2aSThomas Huth float32 ret;
348fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
349fcf5ef2aSThomas Huth ret = int32_to_float32(t0, &env->fp_status);
350fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
351fcf5ef2aSThomas Huth return ret;
352fcf5ef2aSThomas Huth }
353fcf5ef2aSThomas Huth
helper_float_DT(CPUSH4State * env,uint32_t t0)354fcf5ef2aSThomas Huth float64 helper_float_DT(CPUSH4State *env, uint32_t t0)
355fcf5ef2aSThomas Huth {
356fcf5ef2aSThomas Huth float64 ret;
357fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
358fcf5ef2aSThomas Huth ret = int32_to_float64(t0, &env->fp_status);
359fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
360fcf5ef2aSThomas Huth return ret;
361fcf5ef2aSThomas Huth }
362fcf5ef2aSThomas Huth
helper_fmac_FT(CPUSH4State * env,float32 t0,float32 t1,float32 t2)363fcf5ef2aSThomas Huth float32 helper_fmac_FT(CPUSH4State *env, float32 t0, float32 t1, float32 t2)
364fcf5ef2aSThomas Huth {
365fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
366fcf5ef2aSThomas Huth t0 = float32_muladd(t0, t1, t2, 0, &env->fp_status);
367fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
368fcf5ef2aSThomas Huth return t0;
369fcf5ef2aSThomas Huth }
370fcf5ef2aSThomas Huth
helper_fmul_FT(CPUSH4State * env,float32 t0,float32 t1)371fcf5ef2aSThomas Huth float32 helper_fmul_FT(CPUSH4State *env, float32 t0, float32 t1)
372fcf5ef2aSThomas Huth {
373fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
374fcf5ef2aSThomas Huth t0 = float32_mul(t0, t1, &env->fp_status);
375fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
376fcf5ef2aSThomas Huth return t0;
377fcf5ef2aSThomas Huth }
378fcf5ef2aSThomas Huth
helper_fmul_DT(CPUSH4State * env,float64 t0,float64 t1)379fcf5ef2aSThomas Huth float64 helper_fmul_DT(CPUSH4State *env, float64 t0, float64 t1)
380fcf5ef2aSThomas Huth {
381fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
382fcf5ef2aSThomas Huth t0 = float64_mul(t0, t1, &env->fp_status);
383fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
384fcf5ef2aSThomas Huth return t0;
385fcf5ef2aSThomas Huth }
386fcf5ef2aSThomas Huth
helper_fsqrt_FT(CPUSH4State * env,float32 t0)387fcf5ef2aSThomas Huth float32 helper_fsqrt_FT(CPUSH4State *env, float32 t0)
388fcf5ef2aSThomas Huth {
389fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
390fcf5ef2aSThomas Huth t0 = float32_sqrt(t0, &env->fp_status);
391fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
392fcf5ef2aSThomas Huth return t0;
393fcf5ef2aSThomas Huth }
394fcf5ef2aSThomas Huth
helper_fsqrt_DT(CPUSH4State * env,float64 t0)395fcf5ef2aSThomas Huth float64 helper_fsqrt_DT(CPUSH4State *env, float64 t0)
396fcf5ef2aSThomas Huth {
397fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
398fcf5ef2aSThomas Huth t0 = float64_sqrt(t0, &env->fp_status);
399fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
400fcf5ef2aSThomas Huth return t0;
401fcf5ef2aSThomas Huth }
402fcf5ef2aSThomas Huth
helper_fsrra_FT(CPUSH4State * env,float32 t0)40311b7aa23SRichard Henderson float32 helper_fsrra_FT(CPUSH4State *env, float32 t0)
40411b7aa23SRichard Henderson {
40511b7aa23SRichard Henderson set_float_exception_flags(0, &env->fp_status);
40611b7aa23SRichard Henderson /* "Approximate" 1/sqrt(x) via actual computation. */
40711b7aa23SRichard Henderson t0 = float32_sqrt(t0, &env->fp_status);
40811b7aa23SRichard Henderson t0 = float32_div(float32_one, t0, &env->fp_status);
40902b8e735SPhilippe Mathieu-Daudé /*
41002b8e735SPhilippe Mathieu-Daudé * Since this is supposed to be an approximation, an imprecision
41102b8e735SPhilippe Mathieu-Daudé * exception is required. One supposes this also follows the usual
41223b5d9faSLichang Zhao * IEEE rule that other exceptions take precedence.
41302b8e735SPhilippe Mathieu-Daudé */
41411b7aa23SRichard Henderson if (get_float_exception_flags(&env->fp_status) == 0) {
41511b7aa23SRichard Henderson set_float_exception_flags(float_flag_inexact, &env->fp_status);
41611b7aa23SRichard Henderson }
41711b7aa23SRichard Henderson update_fpscr(env, GETPC());
41811b7aa23SRichard Henderson return t0;
41911b7aa23SRichard Henderson }
42011b7aa23SRichard Henderson
helper_fsub_FT(CPUSH4State * env,float32 t0,float32 t1)421fcf5ef2aSThomas Huth float32 helper_fsub_FT(CPUSH4State *env, float32 t0, float32 t1)
422fcf5ef2aSThomas Huth {
423fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
424fcf5ef2aSThomas Huth t0 = float32_sub(t0, t1, &env->fp_status);
425fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
426fcf5ef2aSThomas Huth return t0;
427fcf5ef2aSThomas Huth }
428fcf5ef2aSThomas Huth
helper_fsub_DT(CPUSH4State * env,float64 t0,float64 t1)429fcf5ef2aSThomas Huth float64 helper_fsub_DT(CPUSH4State *env, float64 t0, float64 t1)
430fcf5ef2aSThomas Huth {
431fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
432fcf5ef2aSThomas Huth t0 = float64_sub(t0, t1, &env->fp_status);
433fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
434fcf5ef2aSThomas Huth return t0;
435fcf5ef2aSThomas Huth }
436fcf5ef2aSThomas Huth
helper_ftrc_FT(CPUSH4State * env,float32 t0)437fcf5ef2aSThomas Huth uint32_t helper_ftrc_FT(CPUSH4State *env, float32 t0)
438fcf5ef2aSThomas Huth {
439fcf5ef2aSThomas Huth uint32_t ret;
440fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
441fcf5ef2aSThomas Huth ret = float32_to_int32_round_to_zero(t0, &env->fp_status);
442fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
443fcf5ef2aSThomas Huth return ret;
444fcf5ef2aSThomas Huth }
445fcf5ef2aSThomas Huth
helper_ftrc_DT(CPUSH4State * env,float64 t0)446fcf5ef2aSThomas Huth uint32_t helper_ftrc_DT(CPUSH4State *env, float64 t0)
447fcf5ef2aSThomas Huth {
448fcf5ef2aSThomas Huth uint32_t ret;
449fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
450fcf5ef2aSThomas Huth ret = float64_to_int32_round_to_zero(t0, &env->fp_status);
451fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
452fcf5ef2aSThomas Huth return ret;
453fcf5ef2aSThomas Huth }
454fcf5ef2aSThomas Huth
helper_fipr(CPUSH4State * env,uint32_t m,uint32_t n)455fcf5ef2aSThomas Huth void helper_fipr(CPUSH4State *env, uint32_t m, uint32_t n)
456fcf5ef2aSThomas Huth {
457fcf5ef2aSThomas Huth int bank, i;
458fcf5ef2aSThomas Huth float32 r, p;
459fcf5ef2aSThomas Huth
460fcf5ef2aSThomas Huth bank = (env->sr & FPSCR_FR) ? 16 : 0;
461fcf5ef2aSThomas Huth r = float32_zero;
462fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
463fcf5ef2aSThomas Huth
464fcf5ef2aSThomas Huth for (i = 0 ; i < 4 ; i++) {
465fcf5ef2aSThomas Huth p = float32_mul(env->fregs[bank + m + i],
466fcf5ef2aSThomas Huth env->fregs[bank + n + i],
467fcf5ef2aSThomas Huth &env->fp_status);
468fcf5ef2aSThomas Huth r = float32_add(r, p, &env->fp_status);
469fcf5ef2aSThomas Huth }
470fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
471fcf5ef2aSThomas Huth
472fcf5ef2aSThomas Huth env->fregs[bank + n + 3] = r;
473fcf5ef2aSThomas Huth }
474fcf5ef2aSThomas Huth
helper_ftrv(CPUSH4State * env,uint32_t n)475fcf5ef2aSThomas Huth void helper_ftrv(CPUSH4State *env, uint32_t n)
476fcf5ef2aSThomas Huth {
477fcf5ef2aSThomas Huth int bank_matrix, bank_vector;
478fcf5ef2aSThomas Huth int i, j;
479fcf5ef2aSThomas Huth float32 r[4];
480fcf5ef2aSThomas Huth float32 p;
481fcf5ef2aSThomas Huth
482fcf5ef2aSThomas Huth bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
483fcf5ef2aSThomas Huth bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
484fcf5ef2aSThomas Huth set_float_exception_flags(0, &env->fp_status);
485fcf5ef2aSThomas Huth for (i = 0 ; i < 4 ; i++) {
486fcf5ef2aSThomas Huth r[i] = float32_zero;
487fcf5ef2aSThomas Huth for (j = 0 ; j < 4 ; j++) {
488fcf5ef2aSThomas Huth p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
489fcf5ef2aSThomas Huth env->fregs[bank_vector + j],
490fcf5ef2aSThomas Huth &env->fp_status);
491fcf5ef2aSThomas Huth r[i] = float32_add(r[i], p, &env->fp_status);
492fcf5ef2aSThomas Huth }
493fcf5ef2aSThomas Huth }
494fcf5ef2aSThomas Huth update_fpscr(env, GETPC());
495fcf5ef2aSThomas Huth
496fcf5ef2aSThomas Huth for (i = 0 ; i < 4 ; i++) {
497fcf5ef2aSThomas Huth env->fregs[bank_vector + i] = r[i];
498fcf5ef2aSThomas Huth }
499fcf5ef2aSThomas Huth }
500