blob: 14c3db0f485c78f4e80125d5675e69ed29a2fbda [file] [log] [blame]
bellardfdf9b3e2006-04-27 21:07:38 +00001/*
2 * SH4 emulation
ths5fafdf22007-09-16 21:08:06 +00003 *
bellardfdf9b3e2006-04-27 21:07:38 +00004 * 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
Thomas Huth6faf2b62019-02-13 14:52:50 +01009 * version 2.1 of the License, or (at your option) any later version.
bellardfdf9b3e2006-04-27 21:07:38 +000010 *
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
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellardfdf9b3e2006-04-27 21:07:38 +000018 */
Peter Maydell9d4c9942016-01-26 18:17:20 +000019#include "qemu/osdep.h"
Blue Swirl3e457172011-07-13 12:44:15 +000020#include "cpu.h"
Richard Henderson2ef61752014-04-07 22:31:41 -070021#include "exec/helper-proto.h"
Paolo Bonzini63c91552016-03-15 13:18:37 +010022#include "exec/exec-all.h"
Paolo Bonzinif08b6172014-03-28 19:42:10 +010023#include "exec/cpu_ldst.h"
Alex Bennée24f91e82018-01-19 18:24:22 +000024#include "fpu/softfloat.h"
bellardfdf9b3e2006-04-27 21:07:38 +000025
bellardfdf9b3e2006-04-27 21:07:38 +000026#ifndef CONFIG_USER_ONLY
27
Aurelien Jarno34257c22017-05-01 23:20:43 +020028void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
29 MMUAccessType access_type,
30 int mmu_idx, uintptr_t retaddr)
31{
32 switch (access_type) {
33 case MMU_INST_FETCH:
34 case MMU_DATA_LOAD:
35 cs->exception_index = 0x0e0;
36 break;
37 case MMU_DATA_STORE:
38 cs->exception_index = 0x100;
39 break;
40 }
41 cpu_loop_exit_restore(cs, retaddr);
42}
43
bellardfdf9b3e2006-04-27 21:07:38 +000044#endif
45
Blue Swirl485d0032012-09-02 10:37:06 +000046void helper_ldtlb(CPUSH4State *env)
aurel32ea2b5422008-05-09 18:45:55 +000047{
48#ifdef CONFIG_USER_ONLY
Richard Hendersondad1c8e2019-03-22 19:26:42 -070049 cpu_abort(env_cpu(env), "Unhandled ldtlb");
aurel32ea2b5422008-05-09 18:45:55 +000050#else
51 cpu_load_tlb(env);
52#endif
53}
54
Aurelien Jarno10127402012-09-16 13:12:21 +020055static inline void QEMU_NORETURN raise_exception(CPUSH4State *env, int index,
56 uintptr_t retaddr)
Aurelien Jarnofd4bab12011-01-14 20:39:18 +010057{
Richard Hendersondad1c8e2019-03-22 19:26:42 -070058 CPUState *cs = env_cpu(env);
Andreas Färber27103422013-08-26 08:31:06 +020059
60 cs->exception_index = index;
Aurelien Jarno57e2d412017-05-10 08:58:27 +020061 cpu_loop_exit_restore(cs, retaddr);
Aurelien Jarnofd4bab12011-01-14 20:39:18 +010062}
63
Blue Swirl485d0032012-09-02 10:37:06 +000064void helper_raise_illegal_instruction(CPUSH4State *env)
aurel32e6afc2f2008-08-29 23:01:41 +000065{
Aurelien Jarno10127402012-09-16 13:12:21 +020066 raise_exception(env, 0x180, 0);
aurel32e6afc2f2008-08-29 23:01:41 +000067}
68
Blue Swirl485d0032012-09-02 10:37:06 +000069void helper_raise_slot_illegal_instruction(CPUSH4State *env)
aurel32e6afc2f2008-08-29 23:01:41 +000070{
Aurelien Jarno10127402012-09-16 13:12:21 +020071 raise_exception(env, 0x1a0, 0);
aurel32e6afc2f2008-08-29 23:01:41 +000072}
73
Blue Swirl485d0032012-09-02 10:37:06 +000074void helper_raise_fpu_disable(CPUSH4State *env)
aurel32d8299bc2008-12-07 22:46:31 +000075{
Aurelien Jarno10127402012-09-16 13:12:21 +020076 raise_exception(env, 0x800, 0);
aurel32d8299bc2008-12-07 22:46:31 +000077}
78
Blue Swirl485d0032012-09-02 10:37:06 +000079void helper_raise_slot_fpu_disable(CPUSH4State *env)
aurel32d8299bc2008-12-07 22:46:31 +000080{
Aurelien Jarno10127402012-09-16 13:12:21 +020081 raise_exception(env, 0x820, 0);
aurel32d8299bc2008-12-07 22:46:31 +000082}
83
Blue Swirl485d0032012-09-02 10:37:06 +000084void helper_debug(CPUSH4State *env)
aurel32e6afc2f2008-08-29 23:01:41 +000085{
Aurelien Jarno10127402012-09-16 13:12:21 +020086 raise_exception(env, EXCP_DEBUG, 0);
aurel32e6afc2f2008-08-29 23:01:41 +000087}
88
Aurelien Jarno10127402012-09-16 13:12:21 +020089void helper_sleep(CPUSH4State *env)
aurel32e6afc2f2008-08-29 23:01:41 +000090{
Richard Hendersondad1c8e2019-03-22 19:26:42 -070091 CPUState *cs = env_cpu(env);
Andreas Färber259186a2013-01-17 18:51:17 +010092
93 cs->halted = 1;
Aurelien Jarnoefac4152011-02-24 12:31:41 +010094 env->in_sleep = 1;
Aurelien Jarno10127402012-09-16 13:12:21 +020095 raise_exception(env, EXCP_HLT, 0);
aurel32e6afc2f2008-08-29 23:01:41 +000096}
97
Blue Swirl485d0032012-09-02 10:37:06 +000098void helper_trapa(CPUSH4State *env, uint32_t tra)
aurel32e6afc2f2008-08-29 23:01:41 +000099{
100 env->tra = tra << 2;
Aurelien Jarno10127402012-09-16 13:12:21 +0200101 raise_exception(env, 0x160, 0);
aurel32e6afc2f2008-08-29 23:01:41 +0000102}
103
Richard Henderson4bfa6022017-07-18 10:02:31 -1000104void helper_exclusive(CPUSH4State *env)
105{
106 /* We do not want cpu_restore_state to run. */
Richard Henderson29a0af62019-03-22 16:07:18 -0700107 cpu_loop_exit_atomic(env_cpu(env), 0);
Richard Henderson4bfa6022017-07-18 10:02:31 -1000108}
109
Blue Swirl485d0032012-09-02 10:37:06 +0000110void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value)
edgar_igl852d4812009-04-01 23:10:46 +0000111{
112 if (cpu_sh4_is_cached (env, address))
113 {
Peter Maydell01a72012016-07-12 13:50:59 +0100114 memory_content *r = g_new(memory_content, 1);
115
edgar_igl852d4812009-04-01 23:10:46 +0000116 r->address = address;
117 r->value = value;
118 r->next = NULL;
119
120 *(env->movcal_backup_tail) = r;
121 env->movcal_backup_tail = &(r->next);
122 }
123}
124
Blue Swirl485d0032012-09-02 10:37:06 +0000125void helper_discard_movcal_backup(CPUSH4State *env)
edgar_igl852d4812009-04-01 23:10:46 +0000126{
127 memory_content *current = env->movcal_backup;
128
129 while(current)
130 {
131 memory_content *next = current->next;
Peter Maydell01a72012016-07-12 13:50:59 +0100132 g_free(current);
edgar_igl852d4812009-04-01 23:10:46 +0000133 env->movcal_backup = current = next;
Blue Swirlb9d38e92009-09-21 18:11:34 +0000134 if (current == NULL)
edgar_igl852d4812009-04-01 23:10:46 +0000135 env->movcal_backup_tail = &(env->movcal_backup);
136 }
137}
138
Blue Swirl485d0032012-09-02 10:37:06 +0000139void helper_ocbi(CPUSH4State *env, uint32_t address)
edgar_igl852d4812009-04-01 23:10:46 +0000140{
141 memory_content **current = &(env->movcal_backup);
142 while (*current)
143 {
144 uint32_t a = (*current)->address;
145 if ((a & ~0x1F) == (address & ~0x1F))
146 {
147 memory_content *next = (*current)->next;
Blue Swirl485d0032012-09-02 10:37:06 +0000148 cpu_stl_data(env, a, (*current)->value);
edgar_igl852d4812009-04-01 23:10:46 +0000149
Blue Swirlb9d38e92009-09-21 18:11:34 +0000150 if (next == NULL)
edgar_igl852d4812009-04-01 23:10:46 +0000151 {
152 env->movcal_backup_tail = current;
153 }
154
Peter Maydell01a72012016-07-12 13:50:59 +0100155 g_free(*current);
edgar_igl852d4812009-04-01 23:10:46 +0000156 *current = next;
157 break;
158 }
159 }
160}
161
Blue Swirl485d0032012-09-02 10:37:06 +0000162void helper_macl(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
bellardfdf9b3e2006-04-27 21:07:38 +0000163{
164 int64_t res;
165
166 res = ((uint64_t) env->mach << 32) | env->macl;
aurel326f069392008-08-30 13:55:14 +0000167 res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
bellardfdf9b3e2006-04-27 21:07:38 +0000168 env->mach = (res >> 32) & 0xffffffff;
169 env->macl = res & 0xffffffff;
Aurelien Jarno5ed9a252015-05-25 01:28:56 +0200170 if (env->sr & (1u << SR_S)) {
bellardfdf9b3e2006-04-27 21:07:38 +0000171 if (res < 0)
172 env->mach |= 0xffff0000;
173 else
174 env->mach &= 0x00007fff;
175 }
176}
177
Blue Swirl485d0032012-09-02 10:37:06 +0000178void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
bellardfdf9b3e2006-04-27 21:07:38 +0000179{
180 int64_t res;
181
182 res = ((uint64_t) env->mach << 32) | env->macl;
aurel326f069392008-08-30 13:55:14 +0000183 res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
bellardfdf9b3e2006-04-27 21:07:38 +0000184 env->mach = (res >> 32) & 0xffffffff;
185 env->macl = res & 0xffffffff;
Aurelien Jarno5ed9a252015-05-25 01:28:56 +0200186 if (env->sr & (1u << SR_S)) {
bellardfdf9b3e2006-04-27 21:07:38 +0000187 if (res < -0x80000000) {
188 env->mach = 1;
189 env->macl = 0x80000000;
190 } else if (res > 0x000000007fffffff) {
191 env->mach = 1;
192 env->macl = 0x7fffffff;
193 }
194 }
195}
196
Blue Swirl485d0032012-09-02 10:37:06 +0000197void helper_ld_fpscr(CPUSH4State *env, uint32_t val)
aurel32390af822008-08-30 22:07:52 +0000198{
Aurelien Jarno26ac1ea2011-01-14 20:39:18 +0100199 env->fpscr = val & FPSCR_MASK;
200 if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
aurel32390af822008-08-30 22:07:52 +0000201 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
Aurelien Jarno26ac1ea2011-01-14 20:39:18 +0100202 } else {
aurel32390af822008-08-30 22:07:52 +0000203 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
Aurelien Jarno26ac1ea2011-01-14 20:39:18 +0100204 }
Aurelien Jarnoa0d4ac32011-01-14 20:39:18 +0100205 set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
aurel32390af822008-08-30 22:07:52 +0000206}
aurel32cc4ba6a2008-09-01 22:11:56 +0000207
Blue Swirl485d0032012-09-02 10:37:06 +0000208static void update_fpscr(CPUSH4State *env, uintptr_t retaddr)
Aurelien Jarno21829e92011-01-14 20:39:18 +0100209{
210 int xcpt, cause, enable;
211
212 xcpt = get_float_exception_flags(&env->fp_status);
213
Aurelien Jarno801f4da2017-07-02 20:34:55 +0200214 /* Clear the cause entries */
215 env->fpscr &= ~FPSCR_CAUSE_MASK;
Aurelien Jarno21829e92011-01-14 20:39:18 +0100216
217 if (unlikely(xcpt)) {
218 if (xcpt & float_flag_invalid) {
Aurelien Jarno801f4da2017-07-02 20:34:55 +0200219 env->fpscr |= FPSCR_CAUSE_V;
Aurelien Jarno21829e92011-01-14 20:39:18 +0100220 }
221 if (xcpt & float_flag_divbyzero) {
Aurelien Jarno801f4da2017-07-02 20:34:55 +0200222 env->fpscr |= FPSCR_CAUSE_Z;
Aurelien Jarno21829e92011-01-14 20:39:18 +0100223 }
224 if (xcpt & float_flag_overflow) {
Aurelien Jarno801f4da2017-07-02 20:34:55 +0200225 env->fpscr |= FPSCR_CAUSE_O;
Aurelien Jarno21829e92011-01-14 20:39:18 +0100226 }
227 if (xcpt & float_flag_underflow) {
Aurelien Jarno801f4da2017-07-02 20:34:55 +0200228 env->fpscr |= FPSCR_CAUSE_U;
Aurelien Jarno21829e92011-01-14 20:39:18 +0100229 }
230 if (xcpt & float_flag_inexact) {
Aurelien Jarno801f4da2017-07-02 20:34:55 +0200231 env->fpscr |= FPSCR_CAUSE_I;
Aurelien Jarno21829e92011-01-14 20:39:18 +0100232 }
233
Aurelien Jarno801f4da2017-07-02 20:34:55 +0200234 /* Accumulate in flag entries */
235 env->fpscr |= (env->fpscr & FPSCR_CAUSE_MASK)
236 >> (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT);
Aurelien Jarno21829e92011-01-14 20:39:18 +0100237
238 /* Generate an exception if enabled */
239 cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
240 enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
241 if (cause & enable) {
Aurelien Jarno10127402012-09-16 13:12:21 +0200242 raise_exception(env, 0x120, retaddr);
Aurelien Jarno21829e92011-01-14 20:39:18 +0100243 }
244 }
245}
246
Blue Swirl485d0032012-09-02 10:37:06 +0000247float32 helper_fadd_FT(CPUSH4State *env, float32 t0, float32 t1)
aurel32cc4ba6a2008-09-01 22:11:56 +0000248{
Aurelien Jarno21829e92011-01-14 20:39:18 +0100249 set_float_exception_flags(0, &env->fp_status);
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200250 t0 = float32_add(t0, t1, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000251 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200252 return t0;
aurel32cc4ba6a2008-09-01 22:11:56 +0000253}
254
Blue Swirl485d0032012-09-02 10:37:06 +0000255float64 helper_fadd_DT(CPUSH4State *env, float64 t0, float64 t1)
aurel32cc4ba6a2008-09-01 22:11:56 +0000256{
Aurelien Jarno21829e92011-01-14 20:39:18 +0100257 set_float_exception_flags(0, &env->fp_status);
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200258 t0 = float64_add(t0, t1, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000259 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200260 return t0;
aurel32cc4ba6a2008-09-01 22:11:56 +0000261}
262
Aurelien Jarno92f1f832017-07-02 21:31:25 +0200263uint32_t helper_fcmp_eq_FT(CPUSH4State *env, float32 t0, float32 t1)
aurel32cc4ba6a2008-09-01 22:11:56 +0000264{
Aurelien Jarno21829e92011-01-14 20:39:18 +0100265 int relation;
aurel329850d1e2008-11-19 18:00:39 +0000266
Aurelien Jarno21829e92011-01-14 20:39:18 +0100267 set_float_exception_flags(0, &env->fp_status);
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200268 relation = float32_compare(t0, t1, &env->fp_status);
Aurelien Jarnofea7d772017-07-02 21:23:56 +0200269 update_fpscr(env, GETPC());
Aurelien Jarno92f1f832017-07-02 21:31:25 +0200270 return relation == float_relation_equal;
aurel32cc4ba6a2008-09-01 22:11:56 +0000271}
272
Aurelien Jarno92f1f832017-07-02 21:31:25 +0200273uint32_t helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1)
aurel32cc4ba6a2008-09-01 22:11:56 +0000274{
Aurelien Jarno21829e92011-01-14 20:39:18 +0100275 int relation;
aurel329850d1e2008-11-19 18:00:39 +0000276
Aurelien Jarno21829e92011-01-14 20:39:18 +0100277 set_float_exception_flags(0, &env->fp_status);
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200278 relation = float64_compare(t0, t1, &env->fp_status);
Aurelien Jarnofea7d772017-07-02 21:23:56 +0200279 update_fpscr(env, GETPC());
Aurelien Jarno92f1f832017-07-02 21:31:25 +0200280 return relation == float_relation_equal;
aurel32cc4ba6a2008-09-01 22:11:56 +0000281}
282
Aurelien Jarno92f1f832017-07-02 21:31:25 +0200283uint32_t helper_fcmp_gt_FT(CPUSH4State *env, float32 t0, float32 t1)
aurel32cc4ba6a2008-09-01 22:11:56 +0000284{
Aurelien Jarno21829e92011-01-14 20:39:18 +0100285 int relation;
aurel329850d1e2008-11-19 18:00:39 +0000286
Aurelien Jarno21829e92011-01-14 20:39:18 +0100287 set_float_exception_flags(0, &env->fp_status);
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200288 relation = float32_compare(t0, t1, &env->fp_status);
Aurelien Jarnofea7d772017-07-02 21:23:56 +0200289 update_fpscr(env, GETPC());
Aurelien Jarno92f1f832017-07-02 21:31:25 +0200290 return relation == float_relation_greater;
aurel32cc4ba6a2008-09-01 22:11:56 +0000291}
292
Aurelien Jarno92f1f832017-07-02 21:31:25 +0200293uint32_t helper_fcmp_gt_DT(CPUSH4State *env, float64 t0, float64 t1)
aurel32cc4ba6a2008-09-01 22:11:56 +0000294{
Aurelien Jarno21829e92011-01-14 20:39:18 +0100295 int relation;
aurel329850d1e2008-11-19 18:00:39 +0000296
Aurelien Jarno21829e92011-01-14 20:39:18 +0100297 set_float_exception_flags(0, &env->fp_status);
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200298 relation = float64_compare(t0, t1, &env->fp_status);
Aurelien Jarnofea7d772017-07-02 21:23:56 +0200299 update_fpscr(env, GETPC());
Aurelien Jarno92f1f832017-07-02 21:31:25 +0200300 return relation == float_relation_greater;
aurel32cc4ba6a2008-09-01 22:11:56 +0000301}
302
Blue Swirl485d0032012-09-02 10:37:06 +0000303float64 helper_fcnvsd_FT_DT(CPUSH4State *env, float32 t0)
aurel32cc4ba6a2008-09-01 22:11:56 +0000304{
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200305 float64 ret;
Aurelien Jarno21829e92011-01-14 20:39:18 +0100306 set_float_exception_flags(0, &env->fp_status);
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200307 ret = float32_to_float64(t0, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000308 update_fpscr(env, GETPC());
Aurelien Jarno21829e92011-01-14 20:39:18 +0100309 return ret;
aurel32cc4ba6a2008-09-01 22:11:56 +0000310}
311
Blue Swirl485d0032012-09-02 10:37:06 +0000312float32 helper_fcnvds_DT_FT(CPUSH4State *env, float64 t0)
aurel32cc4ba6a2008-09-01 22:11:56 +0000313{
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200314 float32 ret;
Aurelien Jarno21829e92011-01-14 20:39:18 +0100315 set_float_exception_flags(0, &env->fp_status);
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200316 ret = float64_to_float32(t0, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000317 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200318 return ret;
319}
320
Blue Swirl485d0032012-09-02 10:37:06 +0000321float32 helper_fdiv_FT(CPUSH4State *env, float32 t0, float32 t1)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200322{
323 set_float_exception_flags(0, &env->fp_status);
324 t0 = float32_div(t0, t1, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000325 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200326 return t0;
327}
328
Blue Swirl485d0032012-09-02 10:37:06 +0000329float64 helper_fdiv_DT(CPUSH4State *env, float64 t0, float64 t1)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200330{
331 set_float_exception_flags(0, &env->fp_status);
332 t0 = float64_div(t0, t1, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000333 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200334 return t0;
335}
336
Blue Swirl485d0032012-09-02 10:37:06 +0000337float32 helper_float_FT(CPUSH4State *env, uint32_t t0)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200338{
339 float32 ret;
340 set_float_exception_flags(0, &env->fp_status);
341 ret = int32_to_float32(t0, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000342 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200343 return ret;
344}
345
Blue Swirl485d0032012-09-02 10:37:06 +0000346float64 helper_float_DT(CPUSH4State *env, uint32_t t0)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200347{
348 float64 ret;
349 set_float_exception_flags(0, &env->fp_status);
350 ret = int32_to_float64(t0, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000351 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200352 return ret;
353}
354
Blue Swirl485d0032012-09-02 10:37:06 +0000355float32 helper_fmac_FT(CPUSH4State *env, float32 t0, float32 t1, float32 t2)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200356{
357 set_float_exception_flags(0, &env->fp_status);
Aurelien Jarnoff2086f2012-09-16 13:12:20 +0200358 t0 = float32_muladd(t0, t1, t2, 0, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000359 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200360 return t0;
361}
362
Blue Swirl485d0032012-09-02 10:37:06 +0000363float32 helper_fmul_FT(CPUSH4State *env, float32 t0, float32 t1)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200364{
365 set_float_exception_flags(0, &env->fp_status);
366 t0 = float32_mul(t0, t1, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000367 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200368 return t0;
369}
370
Blue Swirl485d0032012-09-02 10:37:06 +0000371float64 helper_fmul_DT(CPUSH4State *env, float64 t0, float64 t1)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200372{
373 set_float_exception_flags(0, &env->fp_status);
374 t0 = float64_mul(t0, t1, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000375 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200376 return t0;
377}
378
Blue Swirl485d0032012-09-02 10:37:06 +0000379float32 helper_fsqrt_FT(CPUSH4State *env, float32 t0)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200380{
381 set_float_exception_flags(0, &env->fp_status);
382 t0 = float32_sqrt(t0, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000383 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200384 return t0;
385}
386
Blue Swirl485d0032012-09-02 10:37:06 +0000387float64 helper_fsqrt_DT(CPUSH4State *env, float64 t0)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200388{
389 set_float_exception_flags(0, &env->fp_status);
390 t0 = float64_sqrt(t0, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000391 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200392 return t0;
393}
394
Richard Henderson11b7aa22017-07-18 10:02:51 -1000395float32 helper_fsrra_FT(CPUSH4State *env, float32 t0)
396{
397 set_float_exception_flags(0, &env->fp_status);
398 /* "Approximate" 1/sqrt(x) via actual computation. */
399 t0 = float32_sqrt(t0, &env->fp_status);
400 t0 = float32_div(float32_one, t0, &env->fp_status);
401 /* Since this is supposed to be an approximation, an imprecision
402 exception is required. One supposes this also follows the usual
403 IEEE rule that other exceptions take precidence. */
404 if (get_float_exception_flags(&env->fp_status) == 0) {
405 set_float_exception_flags(float_flag_inexact, &env->fp_status);
406 }
407 update_fpscr(env, GETPC());
408 return t0;
409}
410
Blue Swirl485d0032012-09-02 10:37:06 +0000411float32 helper_fsub_FT(CPUSH4State *env, float32 t0, float32 t1)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200412{
413 set_float_exception_flags(0, &env->fp_status);
414 t0 = float32_sub(t0, t1, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000415 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200416 return t0;
417}
418
Blue Swirl485d0032012-09-02 10:37:06 +0000419float64 helper_fsub_DT(CPUSH4State *env, float64 t0, float64 t1)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200420{
421 set_float_exception_flags(0, &env->fp_status);
422 t0 = float64_sub(t0, t1, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000423 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200424 return t0;
425}
426
Blue Swirl485d0032012-09-02 10:37:06 +0000427uint32_t helper_ftrc_FT(CPUSH4State *env, float32 t0)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200428{
429 uint32_t ret;
430 set_float_exception_flags(0, &env->fp_status);
431 ret = float32_to_int32_round_to_zero(t0, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000432 update_fpscr(env, GETPC());
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200433 return ret;
434}
435
Blue Swirl485d0032012-09-02 10:37:06 +0000436uint32_t helper_ftrc_DT(CPUSH4State *env, float64 t0)
Aurelien Jarnod6c424c2011-04-10 21:09:12 +0200437{
438 uint32_t ret;
439 set_float_exception_flags(0, &env->fp_status);
440 ret = float64_to_int32_round_to_zero(t0, &env->fp_status);
Blue Swirl485d0032012-09-02 10:37:06 +0000441 update_fpscr(env, GETPC());
Aurelien Jarno21829e92011-01-14 20:39:18 +0100442 return ret;
aurel32cc4ba6a2008-09-01 22:11:56 +0000443}
Aurelien Jarnoaf8c2bd2011-01-14 20:39:18 +0100444
Blue Swirl485d0032012-09-02 10:37:06 +0000445void helper_fipr(CPUSH4State *env, uint32_t m, uint32_t n)
Aurelien Jarnoaf8c2bd2011-01-14 20:39:18 +0100446{
447 int bank, i;
448 float32 r, p;
449
450 bank = (env->sr & FPSCR_FR) ? 16 : 0;
451 r = float32_zero;
452 set_float_exception_flags(0, &env->fp_status);
453
454 for (i = 0 ; i < 4 ; i++) {
455 p = float32_mul(env->fregs[bank + m + i],
456 env->fregs[bank + n + i],
457 &env->fp_status);
458 r = float32_add(r, p, &env->fp_status);
459 }
Blue Swirl485d0032012-09-02 10:37:06 +0000460 update_fpscr(env, GETPC());
Aurelien Jarnoaf8c2bd2011-01-14 20:39:18 +0100461
462 env->fregs[bank + n + 3] = r;
463}
Aurelien Jarno17075f12011-01-14 20:39:18 +0100464
Blue Swirl485d0032012-09-02 10:37:06 +0000465void helper_ftrv(CPUSH4State *env, uint32_t n)
Aurelien Jarno17075f12011-01-14 20:39:18 +0100466{
467 int bank_matrix, bank_vector;
468 int i, j;
469 float32 r[4];
470 float32 p;
471
472 bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
473 bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
474 set_float_exception_flags(0, &env->fp_status);
475 for (i = 0 ; i < 4 ; i++) {
476 r[i] = float32_zero;
477 for (j = 0 ; j < 4 ; j++) {
478 p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
479 env->fregs[bank_vector + j],
480 &env->fp_status);
481 r[i] = float32_add(r[i], p, &env->fp_status);
482 }
483 }
Blue Swirl485d0032012-09-02 10:37:06 +0000484 update_fpscr(env, GETPC());
Aurelien Jarno17075f12011-01-14 20:39:18 +0100485
486 for (i = 0 ; i < 4 ; i++) {
487 env->fregs[bank_vector + i] = r[i];
488 }
489}