bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 1 | /* |
| 2 | * SH4 emulation |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 3 | * |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 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 |
Blue Swirl | 8167ee8 | 2009-07-16 20:47:01 +0000 | [diff] [blame] | 17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 18 | */ |
| 19 | #include <assert.h> |
edgar_igl | 852d481 | 2009-04-01 23:10:46 +0000 | [diff] [blame] | 20 | #include <stdlib.h> |
Blue Swirl | 3e45717 | 2011-07-13 12:44:15 +0000 | [diff] [blame] | 21 | #include "cpu.h" |
pbrook | a7812ae | 2008-11-17 14:43:54 +0000 | [diff] [blame] | 22 | #include "helper.h" |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 23 | |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 24 | static inline void cpu_restore_state_from_retaddr(CPUSH4State *env, |
| 25 | uintptr_t retaddr) |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 26 | { |
| 27 | TranslationBlock *tb; |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 28 | |
| 29 | if (retaddr) { |
Blue Swirl | 2050396 | 2012-04-09 14:20:20 +0000 | [diff] [blame] | 30 | tb = tb_find_pc(retaddr); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 31 | if (tb) { |
| 32 | /* the PC is inside the translated code. It means that we have |
| 33 | a virtual CPU fault */ |
Blue Swirl | 2050396 | 2012-04-09 14:20:20 +0000 | [diff] [blame] | 34 | cpu_restore_state(tb, env, retaddr); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 35 | } |
| 36 | } |
| 37 | } |
| 38 | |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 39 | #ifndef CONFIG_USER_ONLY |
Blue Swirl | 3e45717 | 2011-07-13 12:44:15 +0000 | [diff] [blame] | 40 | #include "softmmu_exec.h" |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 41 | |
| 42 | #define MMUSUFFIX _mmu |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 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 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 56 | void tlb_fill(CPUSH4State *env, target_ulong addr, int is_write, int mmu_idx, |
Blue Swirl | 2050396 | 2012-04-09 14:20:20 +0000 | [diff] [blame] | 57 | uintptr_t retaddr) |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 58 | { |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 59 | int ret; |
| 60 | |
Blue Swirl | 97b348e | 2011-08-01 16:12:17 +0000 | [diff] [blame] | 61 | ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx); |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 62 | if (ret) { |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 63 | /* now we have a real cpu fault */ |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 64 | cpu_restore_state_from_retaddr(env, retaddr); |
Blue Swirl | 1162c04 | 2011-05-14 12:52:35 +0000 | [diff] [blame] | 65 | cpu_loop_exit(env); |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 66 | } |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | #endif |
| 70 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 71 | void helper_ldtlb(CPUSH4State *env) |
aurel32 | ea2b542 | 2008-05-09 18:45:55 +0000 | [diff] [blame] | 72 | { |
| 73 | #ifdef CONFIG_USER_ONLY |
| 74 | /* XXXXX */ |
Blue Swirl | 43dc2a6 | 2010-03-18 18:41:57 +0000 | [diff] [blame] | 75 | cpu_abort(env, "Unhandled ldtlb"); |
aurel32 | ea2b542 | 2008-05-09 18:45:55 +0000 | [diff] [blame] | 76 | #else |
| 77 | cpu_load_tlb(env); |
| 78 | #endif |
| 79 | } |
| 80 | |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 81 | static inline void QEMU_NORETURN raise_exception(CPUSH4State *env, int index, |
| 82 | uintptr_t retaddr) |
Aurelien Jarno | fd4bab1 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 83 | { |
| 84 | env->exception_index = index; |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 85 | cpu_restore_state_from_retaddr(env, retaddr); |
Blue Swirl | 1162c04 | 2011-05-14 12:52:35 +0000 | [diff] [blame] | 86 | cpu_loop_exit(env); |
Aurelien Jarno | fd4bab1 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 87 | } |
| 88 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 89 | void helper_raise_illegal_instruction(CPUSH4State *env) |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 90 | { |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 91 | raise_exception(env, 0x180, 0); |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 92 | } |
| 93 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 94 | void helper_raise_slot_illegal_instruction(CPUSH4State *env) |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 95 | { |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 96 | raise_exception(env, 0x1a0, 0); |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 97 | } |
| 98 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 99 | void helper_raise_fpu_disable(CPUSH4State *env) |
aurel32 | d8299bc | 2008-12-07 22:46:31 +0000 | [diff] [blame] | 100 | { |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 101 | raise_exception(env, 0x800, 0); |
aurel32 | d8299bc | 2008-12-07 22:46:31 +0000 | [diff] [blame] | 102 | } |
| 103 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 104 | void helper_raise_slot_fpu_disable(CPUSH4State *env) |
aurel32 | d8299bc | 2008-12-07 22:46:31 +0000 | [diff] [blame] | 105 | { |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 106 | raise_exception(env, 0x820, 0); |
aurel32 | d8299bc | 2008-12-07 22:46:31 +0000 | [diff] [blame] | 107 | } |
| 108 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 109 | void helper_debug(CPUSH4State *env) |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 110 | { |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 111 | raise_exception(env, EXCP_DEBUG, 0); |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 112 | } |
| 113 | |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 114 | void helper_sleep(CPUSH4State *env) |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 115 | { |
| 116 | env->halted = 1; |
Aurelien Jarno | efac415 | 2011-02-24 12:31:41 +0100 | [diff] [blame] | 117 | env->in_sleep = 1; |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 118 | raise_exception(env, EXCP_HLT, 0); |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 119 | } |
| 120 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 121 | void helper_trapa(CPUSH4State *env, uint32_t tra) |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 122 | { |
| 123 | env->tra = tra << 2; |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 124 | raise_exception(env, 0x160, 0); |
aurel32 | e6afc2f | 2008-08-29 23:01:41 +0000 | [diff] [blame] | 125 | } |
| 126 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 127 | void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value) |
edgar_igl | 852d481 | 2009-04-01 23:10:46 +0000 | [diff] [blame] | 128 | { |
| 129 | if (cpu_sh4_is_cached (env, address)) |
| 130 | { |
| 131 | memory_content *r = malloc (sizeof(memory_content)); |
| 132 | r->address = address; |
| 133 | r->value = value; |
| 134 | r->next = NULL; |
| 135 | |
| 136 | *(env->movcal_backup_tail) = r; |
| 137 | env->movcal_backup_tail = &(r->next); |
| 138 | } |
| 139 | } |
| 140 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 141 | void helper_discard_movcal_backup(CPUSH4State *env) |
edgar_igl | 852d481 | 2009-04-01 23:10:46 +0000 | [diff] [blame] | 142 | { |
| 143 | memory_content *current = env->movcal_backup; |
| 144 | |
| 145 | while(current) |
| 146 | { |
| 147 | memory_content *next = current->next; |
| 148 | free (current); |
| 149 | env->movcal_backup = current = next; |
Blue Swirl | b9d38e9 | 2009-09-21 18:11:34 +0000 | [diff] [blame] | 150 | if (current == NULL) |
edgar_igl | 852d481 | 2009-04-01 23:10:46 +0000 | [diff] [blame] | 151 | env->movcal_backup_tail = &(env->movcal_backup); |
| 152 | } |
| 153 | } |
| 154 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 155 | void helper_ocbi(CPUSH4State *env, uint32_t address) |
edgar_igl | 852d481 | 2009-04-01 23:10:46 +0000 | [diff] [blame] | 156 | { |
| 157 | memory_content **current = &(env->movcal_backup); |
| 158 | while (*current) |
| 159 | { |
| 160 | uint32_t a = (*current)->address; |
| 161 | if ((a & ~0x1F) == (address & ~0x1F)) |
| 162 | { |
| 163 | memory_content *next = (*current)->next; |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 164 | cpu_stl_data(env, a, (*current)->value); |
edgar_igl | 852d481 | 2009-04-01 23:10:46 +0000 | [diff] [blame] | 165 | |
Blue Swirl | b9d38e9 | 2009-09-21 18:11:34 +0000 | [diff] [blame] | 166 | if (next == NULL) |
edgar_igl | 852d481 | 2009-04-01 23:10:46 +0000 | [diff] [blame] | 167 | { |
| 168 | env->movcal_backup_tail = current; |
| 169 | } |
| 170 | |
| 171 | free (*current); |
| 172 | *current = next; |
| 173 | break; |
| 174 | } |
| 175 | } |
| 176 | } |
| 177 | |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 178 | #define T (env->sr & SR_T) |
| 179 | #define Q (env->sr & SR_Q ? 1 : 0) |
| 180 | #define M (env->sr & SR_M ? 1 : 0) |
| 181 | #define SETT env->sr |= SR_T |
| 182 | #define CLRT env->sr &= ~SR_T |
| 183 | #define SETQ env->sr |= SR_Q |
| 184 | #define CLRQ env->sr &= ~SR_Q |
| 185 | #define SETM env->sr |= SR_M |
| 186 | #define CLRM env->sr &= ~SR_M |
| 187 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 188 | uint32_t helper_div1(CPUSH4State *env, uint32_t arg0, uint32_t arg1) |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 189 | { |
| 190 | uint32_t tmp0, tmp2; |
| 191 | uint8_t old_q, tmp1 = 0xff; |
| 192 | |
aurel32 | 69d6275 | 2008-09-01 13:09:06 +0000 | [diff] [blame] | 193 | //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T); |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 194 | old_q = Q; |
aurel32 | 69d6275 | 2008-09-01 13:09:06 +0000 | [diff] [blame] | 195 | if ((0x80000000 & arg1) != 0) |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 196 | SETQ; |
| 197 | else |
| 198 | CLRQ; |
aurel32 | 69d6275 | 2008-09-01 13:09:06 +0000 | [diff] [blame] | 199 | tmp2 = arg0; |
| 200 | arg1 <<= 1; |
| 201 | arg1 |= T; |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 202 | switch (old_q) { |
| 203 | case 0: |
| 204 | switch (M) { |
| 205 | case 0: |
aurel32 | 69d6275 | 2008-09-01 13:09:06 +0000 | [diff] [blame] | 206 | tmp0 = arg1; |
| 207 | arg1 -= tmp2; |
| 208 | tmp1 = arg1 > tmp0; |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 209 | switch (Q) { |
| 210 | case 0: |
| 211 | if (tmp1) |
| 212 | SETQ; |
| 213 | else |
| 214 | CLRQ; |
| 215 | break; |
| 216 | case 1: |
| 217 | if (tmp1 == 0) |
| 218 | SETQ; |
| 219 | else |
| 220 | CLRQ; |
| 221 | break; |
| 222 | } |
| 223 | break; |
| 224 | case 1: |
aurel32 | 69d6275 | 2008-09-01 13:09:06 +0000 | [diff] [blame] | 225 | tmp0 = arg1; |
| 226 | arg1 += tmp2; |
| 227 | tmp1 = arg1 < tmp0; |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 228 | switch (Q) { |
| 229 | case 0: |
| 230 | if (tmp1 == 0) |
| 231 | SETQ; |
| 232 | else |
| 233 | CLRQ; |
| 234 | break; |
| 235 | case 1: |
| 236 | if (tmp1) |
| 237 | SETQ; |
| 238 | else |
| 239 | CLRQ; |
| 240 | break; |
| 241 | } |
| 242 | break; |
| 243 | } |
| 244 | break; |
| 245 | case 1: |
| 246 | switch (M) { |
| 247 | case 0: |
aurel32 | 69d6275 | 2008-09-01 13:09:06 +0000 | [diff] [blame] | 248 | tmp0 = arg1; |
| 249 | arg1 += tmp2; |
| 250 | tmp1 = arg1 < tmp0; |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 251 | switch (Q) { |
| 252 | case 0: |
| 253 | if (tmp1) |
| 254 | SETQ; |
| 255 | else |
| 256 | CLRQ; |
| 257 | break; |
| 258 | case 1: |
| 259 | if (tmp1 == 0) |
| 260 | SETQ; |
| 261 | else |
| 262 | CLRQ; |
| 263 | break; |
| 264 | } |
| 265 | break; |
| 266 | case 1: |
aurel32 | 69d6275 | 2008-09-01 13:09:06 +0000 | [diff] [blame] | 267 | tmp0 = arg1; |
| 268 | arg1 -= tmp2; |
| 269 | tmp1 = arg1 > tmp0; |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 270 | switch (Q) { |
| 271 | case 0: |
| 272 | if (tmp1 == 0) |
| 273 | SETQ; |
| 274 | else |
| 275 | CLRQ; |
| 276 | break; |
| 277 | case 1: |
| 278 | if (tmp1) |
| 279 | SETQ; |
| 280 | else |
| 281 | CLRQ; |
| 282 | break; |
| 283 | } |
| 284 | break; |
| 285 | } |
| 286 | break; |
| 287 | } |
| 288 | if (Q == M) |
| 289 | SETT; |
| 290 | else |
| 291 | CLRT; |
aurel32 | 69d6275 | 2008-09-01 13:09:06 +0000 | [diff] [blame] | 292 | //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T); |
| 293 | return arg1; |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 294 | } |
| 295 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 296 | void helper_macl(CPUSH4State *env, uint32_t arg0, uint32_t arg1) |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 297 | { |
| 298 | int64_t res; |
| 299 | |
| 300 | res = ((uint64_t) env->mach << 32) | env->macl; |
aurel32 | 6f06939 | 2008-08-30 13:55:14 +0000 | [diff] [blame] | 301 | res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1; |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 302 | env->mach = (res >> 32) & 0xffffffff; |
| 303 | env->macl = res & 0xffffffff; |
| 304 | if (env->sr & SR_S) { |
| 305 | if (res < 0) |
| 306 | env->mach |= 0xffff0000; |
| 307 | else |
| 308 | env->mach &= 0x00007fff; |
| 309 | } |
| 310 | } |
| 311 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 312 | void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1) |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 313 | { |
| 314 | int64_t res; |
| 315 | |
| 316 | res = ((uint64_t) env->mach << 32) | env->macl; |
aurel32 | 6f06939 | 2008-08-30 13:55:14 +0000 | [diff] [blame] | 317 | res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1; |
bellard | fdf9b3e | 2006-04-27 21:07:38 +0000 | [diff] [blame] | 318 | env->mach = (res >> 32) & 0xffffffff; |
| 319 | env->macl = res & 0xffffffff; |
| 320 | if (env->sr & SR_S) { |
| 321 | if (res < -0x80000000) { |
| 322 | env->mach = 1; |
| 323 | env->macl = 0x80000000; |
| 324 | } else if (res > 0x000000007fffffff) { |
| 325 | env->mach = 1; |
| 326 | env->macl = 0x7fffffff; |
| 327 | } |
| 328 | } |
| 329 | } |
| 330 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 331 | static inline void set_t(CPUSH4State *env) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 332 | { |
| 333 | env->sr |= SR_T; |
| 334 | } |
| 335 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 336 | static inline void clr_t(CPUSH4State *env) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 337 | { |
| 338 | env->sr &= ~SR_T; |
| 339 | } |
| 340 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 341 | void helper_ld_fpscr(CPUSH4State *env, uint32_t val) |
aurel32 | 390af82 | 2008-08-30 22:07:52 +0000 | [diff] [blame] | 342 | { |
Aurelien Jarno | 26ac1ea | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 343 | env->fpscr = val & FPSCR_MASK; |
| 344 | if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) { |
aurel32 | 390af82 | 2008-08-30 22:07:52 +0000 | [diff] [blame] | 345 | set_float_rounding_mode(float_round_to_zero, &env->fp_status); |
Aurelien Jarno | 26ac1ea | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 346 | } else { |
aurel32 | 390af82 | 2008-08-30 22:07:52 +0000 | [diff] [blame] | 347 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
Aurelien Jarno | 26ac1ea | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 348 | } |
Aurelien Jarno | a0d4ac3 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 349 | set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status); |
aurel32 | 390af82 | 2008-08-30 22:07:52 +0000 | [diff] [blame] | 350 | } |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 351 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 352 | static void update_fpscr(CPUSH4State *env, uintptr_t retaddr) |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 353 | { |
| 354 | int xcpt, cause, enable; |
| 355 | |
| 356 | xcpt = get_float_exception_flags(&env->fp_status); |
| 357 | |
| 358 | /* Clear the flag entries */ |
| 359 | env->fpscr &= ~FPSCR_FLAG_MASK; |
| 360 | |
| 361 | if (unlikely(xcpt)) { |
| 362 | if (xcpt & float_flag_invalid) { |
| 363 | env->fpscr |= FPSCR_FLAG_V; |
| 364 | } |
| 365 | if (xcpt & float_flag_divbyzero) { |
| 366 | env->fpscr |= FPSCR_FLAG_Z; |
| 367 | } |
| 368 | if (xcpt & float_flag_overflow) { |
| 369 | env->fpscr |= FPSCR_FLAG_O; |
| 370 | } |
| 371 | if (xcpt & float_flag_underflow) { |
| 372 | env->fpscr |= FPSCR_FLAG_U; |
| 373 | } |
| 374 | if (xcpt & float_flag_inexact) { |
| 375 | env->fpscr |= FPSCR_FLAG_I; |
| 376 | } |
| 377 | |
| 378 | /* Accumulate in cause entries */ |
| 379 | env->fpscr |= (env->fpscr & FPSCR_FLAG_MASK) |
| 380 | << (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT); |
| 381 | |
| 382 | /* Generate an exception if enabled */ |
| 383 | cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT; |
| 384 | enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT; |
| 385 | if (cause & enable) { |
Aurelien Jarno | 1012740 | 2012-09-16 13:12:21 +0200 | [diff] [blame] | 386 | raise_exception(env, 0x120, retaddr); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 387 | } |
| 388 | } |
| 389 | } |
| 390 | |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 391 | float32 helper_fabs_FT(float32 t0) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 392 | { |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 393 | return float32_abs(t0); |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 394 | } |
| 395 | |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 396 | float64 helper_fabs_DT(float64 t0) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 397 | { |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 398 | return float64_abs(t0); |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 399 | } |
| 400 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 401 | float32 helper_fadd_FT(CPUSH4State *env, float32 t0, float32 t1) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 402 | { |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 403 | set_float_exception_flags(0, &env->fp_status); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 404 | t0 = float32_add(t0, t1, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 405 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 406 | return t0; |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 407 | } |
| 408 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 409 | float64 helper_fadd_DT(CPUSH4State *env, float64 t0, float64 t1) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 410 | { |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 411 | set_float_exception_flags(0, &env->fp_status); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 412 | t0 = float64_add(t0, t1, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 413 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 414 | return t0; |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 415 | } |
| 416 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 417 | void helper_fcmp_eq_FT(CPUSH4State *env, float32 t0, float32 t1) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 418 | { |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 419 | int relation; |
aurel32 | 9850d1e | 2008-11-19 18:00:39 +0000 | [diff] [blame] | 420 | |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 421 | set_float_exception_flags(0, &env->fp_status); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 422 | relation = float32_compare(t0, t1, &env->fp_status); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 423 | if (unlikely(relation == float_relation_unordered)) { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 424 | update_fpscr(env, GETPC()); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 425 | } else if (relation == float_relation_equal) { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 426 | set_t(env); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 427 | } else { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 428 | clr_t(env); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 429 | } |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 430 | } |
| 431 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 432 | void helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 433 | { |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 434 | int relation; |
aurel32 | 9850d1e | 2008-11-19 18:00:39 +0000 | [diff] [blame] | 435 | |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 436 | set_float_exception_flags(0, &env->fp_status); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 437 | relation = float64_compare(t0, t1, &env->fp_status); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 438 | if (unlikely(relation == float_relation_unordered)) { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 439 | update_fpscr(env, GETPC()); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 440 | } else if (relation == float_relation_equal) { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 441 | set_t(env); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 442 | } else { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 443 | clr_t(env); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 444 | } |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 445 | } |
| 446 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 447 | void helper_fcmp_gt_FT(CPUSH4State *env, float32 t0, float32 t1) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 448 | { |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 449 | int relation; |
aurel32 | 9850d1e | 2008-11-19 18:00:39 +0000 | [diff] [blame] | 450 | |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 451 | set_float_exception_flags(0, &env->fp_status); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 452 | relation = float32_compare(t0, t1, &env->fp_status); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 453 | if (unlikely(relation == float_relation_unordered)) { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 454 | update_fpscr(env, GETPC()); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 455 | } else if (relation == float_relation_greater) { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 456 | set_t(env); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 457 | } else { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 458 | clr_t(env); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 459 | } |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 460 | } |
| 461 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 462 | void helper_fcmp_gt_DT(CPUSH4State *env, float64 t0, float64 t1) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 463 | { |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 464 | int relation; |
aurel32 | 9850d1e | 2008-11-19 18:00:39 +0000 | [diff] [blame] | 465 | |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 466 | set_float_exception_flags(0, &env->fp_status); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 467 | relation = float64_compare(t0, t1, &env->fp_status); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 468 | if (unlikely(relation == float_relation_unordered)) { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 469 | update_fpscr(env, GETPC()); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 470 | } else if (relation == float_relation_greater) { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 471 | set_t(env); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 472 | } else { |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 473 | clr_t(env); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 474 | } |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 475 | } |
| 476 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 477 | float64 helper_fcnvsd_FT_DT(CPUSH4State *env, float32 t0) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 478 | { |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 479 | float64 ret; |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 480 | set_float_exception_flags(0, &env->fp_status); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 481 | ret = float32_to_float64(t0, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 482 | update_fpscr(env, GETPC()); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 483 | return ret; |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 484 | } |
| 485 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 486 | float32 helper_fcnvds_DT_FT(CPUSH4State *env, float64 t0) |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 487 | { |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 488 | float32 ret; |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 489 | set_float_exception_flags(0, &env->fp_status); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 490 | ret = float64_to_float32(t0, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 491 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 492 | return ret; |
| 493 | } |
| 494 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 495 | float32 helper_fdiv_FT(CPUSH4State *env, float32 t0, float32 t1) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 496 | { |
| 497 | set_float_exception_flags(0, &env->fp_status); |
| 498 | t0 = float32_div(t0, t1, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 499 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 500 | return t0; |
| 501 | } |
| 502 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 503 | float64 helper_fdiv_DT(CPUSH4State *env, float64 t0, float64 t1) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 504 | { |
| 505 | set_float_exception_flags(0, &env->fp_status); |
| 506 | t0 = float64_div(t0, t1, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 507 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 508 | return t0; |
| 509 | } |
| 510 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 511 | float32 helper_float_FT(CPUSH4State *env, uint32_t t0) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 512 | { |
| 513 | float32 ret; |
| 514 | set_float_exception_flags(0, &env->fp_status); |
| 515 | ret = int32_to_float32(t0, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 516 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 517 | return ret; |
| 518 | } |
| 519 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 520 | float64 helper_float_DT(CPUSH4State *env, uint32_t t0) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 521 | { |
| 522 | float64 ret; |
| 523 | set_float_exception_flags(0, &env->fp_status); |
| 524 | ret = int32_to_float64(t0, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 525 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 526 | return ret; |
| 527 | } |
| 528 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 529 | float32 helper_fmac_FT(CPUSH4State *env, float32 t0, float32 t1, float32 t2) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 530 | { |
| 531 | set_float_exception_flags(0, &env->fp_status); |
Aurelien Jarno | ff2086f | 2012-09-16 13:12:20 +0200 | [diff] [blame] | 532 | t0 = float32_muladd(t0, t1, t2, 0, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 533 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 534 | return t0; |
| 535 | } |
| 536 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 537 | float32 helper_fmul_FT(CPUSH4State *env, float32 t0, float32 t1) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 538 | { |
| 539 | set_float_exception_flags(0, &env->fp_status); |
| 540 | t0 = float32_mul(t0, t1, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 541 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 542 | return t0; |
| 543 | } |
| 544 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 545 | float64 helper_fmul_DT(CPUSH4State *env, float64 t0, float64 t1) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 546 | { |
| 547 | set_float_exception_flags(0, &env->fp_status); |
| 548 | t0 = float64_mul(t0, t1, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 549 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 550 | return t0; |
| 551 | } |
| 552 | |
| 553 | float32 helper_fneg_T(float32 t0) |
| 554 | { |
| 555 | return float32_chs(t0); |
| 556 | } |
| 557 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 558 | float32 helper_fsqrt_FT(CPUSH4State *env, float32 t0) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 559 | { |
| 560 | set_float_exception_flags(0, &env->fp_status); |
| 561 | t0 = float32_sqrt(t0, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 562 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 563 | return t0; |
| 564 | } |
| 565 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 566 | float64 helper_fsqrt_DT(CPUSH4State *env, float64 t0) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 567 | { |
| 568 | set_float_exception_flags(0, &env->fp_status); |
| 569 | t0 = float64_sqrt(t0, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 570 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 571 | return t0; |
| 572 | } |
| 573 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 574 | float32 helper_fsub_FT(CPUSH4State *env, float32 t0, float32 t1) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 575 | { |
| 576 | set_float_exception_flags(0, &env->fp_status); |
| 577 | t0 = float32_sub(t0, t1, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 578 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 579 | return t0; |
| 580 | } |
| 581 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 582 | float64 helper_fsub_DT(CPUSH4State *env, float64 t0, float64 t1) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 583 | { |
| 584 | set_float_exception_flags(0, &env->fp_status); |
| 585 | t0 = float64_sub(t0, t1, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 586 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 587 | return t0; |
| 588 | } |
| 589 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 590 | uint32_t helper_ftrc_FT(CPUSH4State *env, float32 t0) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 591 | { |
| 592 | uint32_t ret; |
| 593 | set_float_exception_flags(0, &env->fp_status); |
| 594 | ret = float32_to_int32_round_to_zero(t0, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 595 | update_fpscr(env, GETPC()); |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 596 | return ret; |
| 597 | } |
| 598 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 599 | uint32_t helper_ftrc_DT(CPUSH4State *env, float64 t0) |
Aurelien Jarno | d6c424c | 2011-04-10 21:09:12 +0200 | [diff] [blame] | 600 | { |
| 601 | uint32_t ret; |
| 602 | set_float_exception_flags(0, &env->fp_status); |
| 603 | ret = float64_to_int32_round_to_zero(t0, &env->fp_status); |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 604 | update_fpscr(env, GETPC()); |
Aurelien Jarno | 21829e9 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 605 | return ret; |
aurel32 | cc4ba6a | 2008-09-01 22:11:56 +0000 | [diff] [blame] | 606 | } |
Aurelien Jarno | af8c2bd | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 607 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 608 | void helper_fipr(CPUSH4State *env, uint32_t m, uint32_t n) |
Aurelien Jarno | af8c2bd | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 609 | { |
| 610 | int bank, i; |
| 611 | float32 r, p; |
| 612 | |
| 613 | bank = (env->sr & FPSCR_FR) ? 16 : 0; |
| 614 | r = float32_zero; |
| 615 | set_float_exception_flags(0, &env->fp_status); |
| 616 | |
| 617 | for (i = 0 ; i < 4 ; i++) { |
| 618 | p = float32_mul(env->fregs[bank + m + i], |
| 619 | env->fregs[bank + n + i], |
| 620 | &env->fp_status); |
| 621 | r = float32_add(r, p, &env->fp_status); |
| 622 | } |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 623 | update_fpscr(env, GETPC()); |
Aurelien Jarno | af8c2bd | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 624 | |
| 625 | env->fregs[bank + n + 3] = r; |
| 626 | } |
Aurelien Jarno | 17075f1 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 627 | |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 628 | void helper_ftrv(CPUSH4State *env, uint32_t n) |
Aurelien Jarno | 17075f1 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 629 | { |
| 630 | int bank_matrix, bank_vector; |
| 631 | int i, j; |
| 632 | float32 r[4]; |
| 633 | float32 p; |
| 634 | |
| 635 | bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16; |
| 636 | bank_vector = (env->sr & FPSCR_FR) ? 16 : 0; |
| 637 | set_float_exception_flags(0, &env->fp_status); |
| 638 | for (i = 0 ; i < 4 ; i++) { |
| 639 | r[i] = float32_zero; |
| 640 | for (j = 0 ; j < 4 ; j++) { |
| 641 | p = float32_mul(env->fregs[bank_matrix + 4 * j + i], |
| 642 | env->fregs[bank_vector + j], |
| 643 | &env->fp_status); |
| 644 | r[i] = float32_add(r[i], p, &env->fp_status); |
| 645 | } |
| 646 | } |
Blue Swirl | 485d003 | 2012-09-02 10:37:06 +0000 | [diff] [blame] | 647 | update_fpscr(env, GETPC()); |
Aurelien Jarno | 17075f1 | 2011-01-14 20:39:18 +0100 | [diff] [blame] | 648 | |
| 649 | for (i = 0 ; i < 4 ; i++) { |
| 650 | env->fregs[bank_vector + i] = r[i]; |
| 651 | } |
| 652 | } |