bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 1 | /* |
| 2 | * MIPS emulation helpers for qemu. |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 3 | * |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 4 | * Copyright (c) 2004-2005 Jocelyn Mayer |
| 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 |
| 17 | * License along with this library; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ |
ths | 2d0e944 | 2007-04-02 15:54:05 +0000 | [diff] [blame] | 20 | #include <stdlib.h> |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 21 | #include "exec.h" |
| 22 | |
ths | 05f778c | 2007-10-27 13:05:54 +0000 | [diff] [blame] | 23 | #include "host-utils.h" |
| 24 | |
ths | 273af66 | 2007-10-29 14:39:49 +0000 | [diff] [blame] | 25 | #ifdef __s390__ |
| 26 | # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL)) |
| 27 | #else |
| 28 | # define GETPC() (__builtin_return_address(0)) |
| 29 | #endif |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 30 | |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 31 | /*****************************************************************************/ |
| 32 | /* Exceptions processing helpers */ |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 33 | |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 34 | void do_raise_exception_err (uint32_t exception, int error_code) |
| 35 | { |
| 36 | #if 1 |
| 37 | if (logfile && exception < 0x100) |
| 38 | fprintf(logfile, "%s: %d %d\n", __func__, exception, error_code); |
| 39 | #endif |
| 40 | env->exception_index = exception; |
| 41 | env->error_code = error_code; |
| 42 | T0 = 0; |
| 43 | cpu_loop_exit(); |
| 44 | } |
| 45 | |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 46 | void do_raise_exception (uint32_t exception) |
| 47 | { |
| 48 | do_raise_exception_err(exception, 0); |
| 49 | } |
| 50 | |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 51 | void do_restore_state (void *pc_ptr) |
| 52 | { |
| 53 | TranslationBlock *tb; |
| 54 | unsigned long pc = (unsigned long) pc_ptr; |
| 55 | |
| 56 | tb = tb_find_pc (pc); |
| 57 | cpu_restore_state (tb, env, pc, NULL); |
| 58 | } |
| 59 | |
ths | e397ee3 | 2007-03-23 00:43:28 +0000 | [diff] [blame] | 60 | void do_raise_exception_direct_err (uint32_t exception, int error_code) |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 61 | { |
| 62 | do_restore_state (GETPC ()); |
ths | e397ee3 | 2007-03-23 00:43:28 +0000 | [diff] [blame] | 63 | do_raise_exception_err (exception, error_code); |
| 64 | } |
| 65 | |
| 66 | void do_raise_exception_direct (uint32_t exception) |
| 67 | { |
| 68 | do_raise_exception_direct_err (exception, 0); |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 69 | } |
| 70 | |
ths | d26bc21 | 2007-11-08 18:05:37 +0000 | [diff] [blame] | 71 | #if defined(TARGET_MIPS64) |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 72 | #if TARGET_LONG_BITS > HOST_LONG_BITS |
| 73 | /* Those might call libgcc functions. */ |
| 74 | void do_dsll (void) |
| 75 | { |
| 76 | T0 = T0 << T1; |
| 77 | } |
| 78 | |
| 79 | void do_dsll32 (void) |
| 80 | { |
| 81 | T0 = T0 << (T1 + 32); |
| 82 | } |
| 83 | |
| 84 | void do_dsra (void) |
| 85 | { |
| 86 | T0 = (int64_t)T0 >> T1; |
| 87 | } |
| 88 | |
| 89 | void do_dsra32 (void) |
| 90 | { |
| 91 | T0 = (int64_t)T0 >> (T1 + 32); |
| 92 | } |
| 93 | |
| 94 | void do_dsrl (void) |
| 95 | { |
| 96 | T0 = T0 >> T1; |
| 97 | } |
| 98 | |
| 99 | void do_dsrl32 (void) |
| 100 | { |
| 101 | T0 = T0 >> (T1 + 32); |
| 102 | } |
| 103 | |
| 104 | void do_drotr (void) |
| 105 | { |
| 106 | target_ulong tmp; |
| 107 | |
| 108 | if (T1) { |
ths | c6d6dd7 | 2007-11-18 03:36:07 +0000 | [diff] [blame] | 109 | tmp = T0 << (0x40 - T1); |
| 110 | T0 = (T0 >> T1) | tmp; |
ths | 5a63bcb | 2007-04-05 23:20:05 +0000 | [diff] [blame] | 111 | } |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | void do_drotr32 (void) |
| 115 | { |
| 116 | target_ulong tmp; |
| 117 | |
ths | c6d6dd7 | 2007-11-18 03:36:07 +0000 | [diff] [blame] | 118 | tmp = T0 << (0x40 - (32 + T1)); |
| 119 | T0 = (T0 >> (32 + T1)) | tmp; |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | void do_dsllv (void) |
| 123 | { |
| 124 | T0 = T1 << (T0 & 0x3F); |
| 125 | } |
| 126 | |
| 127 | void do_dsrav (void) |
| 128 | { |
| 129 | T0 = (int64_t)T1 >> (T0 & 0x3F); |
| 130 | } |
| 131 | |
| 132 | void do_dsrlv (void) |
| 133 | { |
| 134 | T0 = T1 >> (T0 & 0x3F); |
| 135 | } |
| 136 | |
| 137 | void do_drotrv (void) |
| 138 | { |
| 139 | target_ulong tmp; |
| 140 | |
| 141 | T0 &= 0x3F; |
| 142 | if (T0) { |
ths | c6d6dd7 | 2007-11-18 03:36:07 +0000 | [diff] [blame] | 143 | tmp = T1 << (0x40 - T0); |
| 144 | T0 = (T1 >> T0) | tmp; |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 145 | } else |
ths | c6d6dd7 | 2007-11-18 03:36:07 +0000 | [diff] [blame] | 146 | T0 = T1; |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 147 | } |
ths | 05f778c | 2007-10-27 13:05:54 +0000 | [diff] [blame] | 148 | |
| 149 | void do_dclo (void) |
| 150 | { |
| 151 | T0 = clo64(T0); |
| 152 | } |
| 153 | |
| 154 | void do_dclz (void) |
| 155 | { |
| 156 | T0 = clz64(T0); |
| 157 | } |
| 158 | |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 159 | #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */ |
ths | d26bc21 | 2007-11-08 18:05:37 +0000 | [diff] [blame] | 160 | #endif /* TARGET_MIPS64 */ |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 161 | |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 162 | /* 64 bits arithmetic for 32 bits hosts */ |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 163 | #if TARGET_LONG_BITS > HOST_LONG_BITS |
ths | aa34373 | 2007-10-09 03:39:58 +0000 | [diff] [blame] | 164 | static always_inline uint64_t get_HILO (void) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 165 | { |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 166 | return (env->HI[env->current_tc][0] << 32) | (uint32_t)env->LO[env->current_tc][0]; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 167 | } |
| 168 | |
ths | aa34373 | 2007-10-09 03:39:58 +0000 | [diff] [blame] | 169 | static always_inline void set_HILO (uint64_t HILO) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 170 | { |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 171 | env->LO[env->current_tc][0] = (int32_t)HILO; |
| 172 | env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 173 | } |
| 174 | |
ths | e9c71dd | 2007-12-25 20:46:56 +0000 | [diff] [blame] | 175 | static always_inline void set_HIT0_LO (uint64_t HILO) |
| 176 | { |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 177 | env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF); |
| 178 | T0 = env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); |
ths | e9c71dd | 2007-12-25 20:46:56 +0000 | [diff] [blame] | 179 | } |
| 180 | |
| 181 | static always_inline void set_HI_LOT0 (uint64_t HILO) |
| 182 | { |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 183 | T0 = env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF); |
| 184 | env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); |
ths | e9c71dd | 2007-12-25 20:46:56 +0000 | [diff] [blame] | 185 | } |
| 186 | |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 187 | void do_mult (void) |
| 188 | { |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 189 | set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 190 | } |
| 191 | |
| 192 | void do_multu (void) |
| 193 | { |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 194 | set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | void do_madd (void) |
| 198 | { |
| 199 | int64_t tmp; |
| 200 | |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 201 | tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 202 | set_HILO((int64_t)get_HILO() + tmp); |
| 203 | } |
| 204 | |
| 205 | void do_maddu (void) |
| 206 | { |
| 207 | uint64_t tmp; |
| 208 | |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 209 | tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 210 | set_HILO(get_HILO() + tmp); |
| 211 | } |
| 212 | |
| 213 | void do_msub (void) |
| 214 | { |
| 215 | int64_t tmp; |
| 216 | |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 217 | tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 218 | set_HILO((int64_t)get_HILO() - tmp); |
| 219 | } |
| 220 | |
| 221 | void do_msubu (void) |
| 222 | { |
| 223 | uint64_t tmp; |
| 224 | |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 225 | tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 226 | set_HILO(get_HILO() - tmp); |
| 227 | } |
ths | e9c71dd | 2007-12-25 20:46:56 +0000 | [diff] [blame] | 228 | |
| 229 | /* Multiplication variants of the vr54xx. */ |
| 230 | void do_muls (void) |
| 231 | { |
| 232 | set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1)); |
| 233 | } |
| 234 | |
| 235 | void do_mulsu (void) |
| 236 | { |
| 237 | set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1)); |
| 238 | } |
| 239 | |
| 240 | void do_macc (void) |
| 241 | { |
| 242 | set_HI_LOT0(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1)); |
| 243 | } |
| 244 | |
| 245 | void do_macchi (void) |
| 246 | { |
| 247 | set_HIT0_LO(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1)); |
| 248 | } |
| 249 | |
| 250 | void do_maccu (void) |
| 251 | { |
| 252 | set_HI_LOT0(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1)); |
| 253 | } |
| 254 | |
| 255 | void do_macchiu (void) |
| 256 | { |
| 257 | set_HIT0_LO(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1)); |
| 258 | } |
| 259 | |
| 260 | void do_msac (void) |
| 261 | { |
| 262 | set_HI_LOT0(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1)); |
| 263 | } |
| 264 | |
| 265 | void do_msachi (void) |
| 266 | { |
| 267 | set_HIT0_LO(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1)); |
| 268 | } |
| 269 | |
| 270 | void do_msacu (void) |
| 271 | { |
| 272 | set_HI_LOT0(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1)); |
| 273 | } |
| 274 | |
| 275 | void do_msachiu (void) |
| 276 | { |
| 277 | set_HIT0_LO(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1)); |
| 278 | } |
| 279 | |
| 280 | void do_mulhi (void) |
| 281 | { |
| 282 | set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); |
| 283 | } |
| 284 | |
| 285 | void do_mulhiu (void) |
| 286 | { |
| 287 | set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); |
| 288 | } |
| 289 | |
| 290 | void do_mulshi (void) |
| 291 | { |
| 292 | set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1)); |
| 293 | } |
| 294 | |
| 295 | void do_mulshiu (void) |
| 296 | { |
| 297 | set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1)); |
| 298 | } |
| 299 | #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */ |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 300 | |
ths | 80c2719 | 2007-04-15 21:21:33 +0000 | [diff] [blame] | 301 | #if HOST_LONG_BITS < 64 |
| 302 | void do_div (void) |
| 303 | { |
| 304 | /* 64bit datatypes because we may see overflow/underflow. */ |
| 305 | if (T1 != 0) { |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 306 | env->LO[env->current_tc][0] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1); |
| 307 | env->HI[env->current_tc][0] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1); |
ths | 80c2719 | 2007-04-15 21:21:33 +0000 | [diff] [blame] | 308 | } |
| 309 | } |
| 310 | #endif |
| 311 | |
ths | d26bc21 | 2007-11-08 18:05:37 +0000 | [diff] [blame] | 312 | #if defined(TARGET_MIPS64) |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 313 | void do_ddiv (void) |
| 314 | { |
| 315 | if (T1 != 0) { |
ths | 306ab3e | 2007-12-25 03:18:19 +0000 | [diff] [blame] | 316 | int64_t arg0 = (int64_t)T0; |
| 317 | int64_t arg1 = (int64_t)T1; |
| 318 | if (arg0 == ((int64_t)-1 << 63) && arg1 == (int64_t)-1) { |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 319 | env->LO[env->current_tc][0] = arg0; |
| 320 | env->HI[env->current_tc][0] = 0; |
ths | 306ab3e | 2007-12-25 03:18:19 +0000 | [diff] [blame] | 321 | } else { |
| 322 | lldiv_t res = lldiv(arg0, arg1); |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 323 | env->LO[env->current_tc][0] = res.quot; |
| 324 | env->HI[env->current_tc][0] = res.rem; |
ths | 306ab3e | 2007-12-25 03:18:19 +0000 | [diff] [blame] | 325 | } |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 326 | } |
| 327 | } |
| 328 | |
ths | 12a4b2a | 2007-05-28 17:36:30 +0000 | [diff] [blame] | 329 | #if TARGET_LONG_BITS > HOST_LONG_BITS |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 330 | void do_ddivu (void) |
| 331 | { |
| 332 | if (T1 != 0) { |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 333 | env->LO[env->current_tc][0] = T0 / T1; |
| 334 | env->HI[env->current_tc][0] = T0 % T1; |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 335 | } |
| 336 | } |
| 337 | #endif |
ths | d26bc21 | 2007-11-08 18:05:37 +0000 | [diff] [blame] | 338 | #endif /* TARGET_MIPS64 */ |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 339 | |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 340 | #if defined(CONFIG_USER_ONLY) |
ths | 873eb01 | 2006-12-06 17:59:07 +0000 | [diff] [blame] | 341 | void do_mfc0_random (void) |
bellard | 048f6b4 | 2005-11-26 18:47:20 +0000 | [diff] [blame] | 342 | { |
ths | 873eb01 | 2006-12-06 17:59:07 +0000 | [diff] [blame] | 343 | cpu_abort(env, "mfc0 random\n"); |
bellard | 048f6b4 | 2005-11-26 18:47:20 +0000 | [diff] [blame] | 344 | } |
ths | 873eb01 | 2006-12-06 17:59:07 +0000 | [diff] [blame] | 345 | |
| 346 | void do_mfc0_count (void) |
| 347 | { |
| 348 | cpu_abort(env, "mfc0 count\n"); |
| 349 | } |
| 350 | |
ths | 8c0fdd8 | 2006-12-06 18:19:33 +0000 | [diff] [blame] | 351 | void cpu_mips_store_count(CPUState *env, uint32_t value) |
bellard | 048f6b4 | 2005-11-26 18:47:20 +0000 | [diff] [blame] | 352 | { |
ths | 8c0fdd8 | 2006-12-06 18:19:33 +0000 | [diff] [blame] | 353 | cpu_abort(env, "mtc0 count\n"); |
| 354 | } |
| 355 | |
| 356 | void cpu_mips_store_compare(CPUState *env, uint32_t value) |
| 357 | { |
| 358 | cpu_abort(env, "mtc0 compare\n"); |
| 359 | } |
| 360 | |
ths | 4253218 | 2007-09-25 16:53:15 +0000 | [diff] [blame] | 361 | void cpu_mips_start_count(CPUState *env) |
| 362 | { |
| 363 | cpu_abort(env, "start count\n"); |
| 364 | } |
| 365 | |
| 366 | void cpu_mips_stop_count(CPUState *env) |
| 367 | { |
| 368 | cpu_abort(env, "stop count\n"); |
| 369 | } |
| 370 | |
ths | 4de9b24 | 2007-01-24 01:47:51 +0000 | [diff] [blame] | 371 | void cpu_mips_update_irq(CPUState *env) |
| 372 | { |
| 373 | cpu_abort(env, "mtc0 status / mtc0 cause\n"); |
| 374 | } |
| 375 | |
ths | 8c0fdd8 | 2006-12-06 18:19:33 +0000 | [diff] [blame] | 376 | void do_mtc0_status_debug(uint32_t old, uint32_t val) |
| 377 | { |
ths | 7a387ff | 2006-12-06 20:17:30 +0000 | [diff] [blame] | 378 | cpu_abort(env, "mtc0 status debug\n"); |
ths | 8c0fdd8 | 2006-12-06 18:19:33 +0000 | [diff] [blame] | 379 | } |
| 380 | |
ths | 7a387ff | 2006-12-06 20:17:30 +0000 | [diff] [blame] | 381 | void do_mtc0_status_irqraise_debug (void) |
ths | 8c0fdd8 | 2006-12-06 18:19:33 +0000 | [diff] [blame] | 382 | { |
ths | 7a387ff | 2006-12-06 20:17:30 +0000 | [diff] [blame] | 383 | cpu_abort(env, "mtc0 status irqraise debug\n"); |
bellard | 048f6b4 | 2005-11-26 18:47:20 +0000 | [diff] [blame] | 384 | } |
| 385 | |
ths | 8c0fdd8 | 2006-12-06 18:19:33 +0000 | [diff] [blame] | 386 | void cpu_mips_tlb_flush (CPUState *env, int flush_global) |
| 387 | { |
| 388 | cpu_abort(env, "mips_tlb_flush\n"); |
| 389 | } |
| 390 | |
bellard | 048f6b4 | 2005-11-26 18:47:20 +0000 | [diff] [blame] | 391 | #else |
| 392 | |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 393 | /* CP0 helpers */ |
ths | 873eb01 | 2006-12-06 17:59:07 +0000 | [diff] [blame] | 394 | void do_mfc0_random (void) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 395 | { |
ths | 5dc4b74 | 2006-12-21 13:48:28 +0000 | [diff] [blame] | 396 | T0 = (int32_t)cpu_mips_get_random(env); |
ths | 873eb01 | 2006-12-06 17:59:07 +0000 | [diff] [blame] | 397 | } |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 398 | |
ths | 873eb01 | 2006-12-06 17:59:07 +0000 | [diff] [blame] | 399 | void do_mfc0_count (void) |
| 400 | { |
ths | 5dc4b74 | 2006-12-21 13:48:28 +0000 | [diff] [blame] | 401 | T0 = (int32_t)cpu_mips_get_count(env); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 402 | } |
| 403 | |
ths | 8c0fdd8 | 2006-12-06 18:19:33 +0000 | [diff] [blame] | 404 | void do_mtc0_status_debug(uint32_t old, uint32_t val) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 405 | { |
ths | f41c52f | 2007-04-06 18:46:01 +0000 | [diff] [blame] | 406 | fprintf(logfile, "Status %08x (%08x) => %08x (%08x) Cause %08x", |
| 407 | old, old & env->CP0_Cause & CP0Ca_IP_mask, |
| 408 | val, val & env->CP0_Cause & CP0Ca_IP_mask, |
| 409 | env->CP0_Cause); |
ths | 623a930 | 2007-10-28 19:45:05 +0000 | [diff] [blame] | 410 | switch (env->hflags & MIPS_HFLAG_KSU) { |
| 411 | case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break; |
| 412 | case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break; |
| 413 | case MIPS_HFLAG_KM: fputs("\n", logfile); break; |
| 414 | default: cpu_abort(env, "Invalid MMU mode!\n"); break; |
| 415 | } |
ths | 8c0fdd8 | 2006-12-06 18:19:33 +0000 | [diff] [blame] | 416 | } |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 417 | |
ths | 8c0fdd8 | 2006-12-06 18:19:33 +0000 | [diff] [blame] | 418 | void do_mtc0_status_irqraise_debug(void) |
| 419 | { |
| 420 | fprintf(logfile, "Raise pending IRQs\n"); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 421 | } |
| 422 | |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 423 | void fpu_handle_exception(void) |
| 424 | { |
| 425 | #ifdef CONFIG_SOFTFLOAT |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 426 | int flags = get_float_exception_flags(&env->fpu->fp_status); |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 427 | unsigned int cpuflags = 0, enable, cause = 0; |
| 428 | |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 429 | enable = GET_FP_ENABLE(env->fpu->fcr31); |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 430 | |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 431 | /* determine current flags */ |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 432 | if (flags & float_flag_invalid) { |
| 433 | cpuflags |= FP_INVALID; |
| 434 | cause |= FP_INVALID & enable; |
| 435 | } |
| 436 | if (flags & float_flag_divbyzero) { |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 437 | cpuflags |= FP_DIV0; |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 438 | cause |= FP_DIV0 & enable; |
| 439 | } |
| 440 | if (flags & float_flag_overflow) { |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 441 | cpuflags |= FP_OVERFLOW; |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 442 | cause |= FP_OVERFLOW & enable; |
| 443 | } |
| 444 | if (flags & float_flag_underflow) { |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 445 | cpuflags |= FP_UNDERFLOW; |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 446 | cause |= FP_UNDERFLOW & enable; |
| 447 | } |
| 448 | if (flags & float_flag_inexact) { |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 449 | cpuflags |= FP_INEXACT; |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 450 | cause |= FP_INEXACT & enable; |
| 451 | } |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 452 | SET_FP_FLAGS(env->fpu->fcr31, cpuflags); |
| 453 | SET_FP_CAUSE(env->fpu->fcr31, cause); |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 454 | #else |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 455 | SET_FP_FLAGS(env->fpu->fcr31, 0); |
| 456 | SET_FP_CAUSE(env->fpu->fcr31, 0); |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 457 | #endif |
| 458 | } |
bellard | 6ea83fe | 2006-06-14 12:56:19 +0000 | [diff] [blame] | 459 | |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 460 | /* TLB management */ |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 461 | void cpu_mips_tlb_flush (CPUState *env, int flush_global) |
| 462 | { |
| 463 | /* Flush qemu's TLB and discard all shadowed entries. */ |
| 464 | tlb_flush (env, flush_global); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 465 | env->tlb->tlb_in_use = env->tlb->nb_tlb; |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 466 | } |
| 467 | |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 468 | static void r4k_mips_tlb_flush_extra (CPUState *env, int first) |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 469 | { |
| 470 | /* Discard entries from env->tlb[first] onwards. */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 471 | while (env->tlb->tlb_in_use > first) { |
| 472 | r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0); |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 473 | } |
| 474 | } |
| 475 | |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 476 | static void r4k_fill_tlb (int idx) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 477 | { |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 478 | r4k_tlb_t *tlb; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 479 | |
| 480 | /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 481 | tlb = &env->tlb->mmu.r4k.tlb[idx]; |
ths | f2e9ebe | 2007-05-13 14:07:26 +0000 | [diff] [blame] | 482 | tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); |
ths | d26bc21 | 2007-11-08 18:05:37 +0000 | [diff] [blame] | 483 | #if defined(TARGET_MIPS64) |
ths | e034e2c | 2007-06-23 18:04:12 +0000 | [diff] [blame] | 484 | tlb->VPN &= env->SEGMask; |
ths | 100ce98 | 2007-05-13 19:22:13 +0000 | [diff] [blame] | 485 | #endif |
pbrook | 98c1b82 | 2006-03-11 16:20:36 +0000 | [diff] [blame] | 486 | tlb->ASID = env->CP0_EntryHi & 0xFF; |
ths | 3b1c8be | 2007-01-22 20:50:42 +0000 | [diff] [blame] | 487 | tlb->PageMask = env->CP0_PageMask; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 488 | tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; |
pbrook | 98c1b82 | 2006-03-11 16:20:36 +0000 | [diff] [blame] | 489 | tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; |
| 490 | tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; |
| 491 | tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 492 | tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12; |
pbrook | 98c1b82 | 2006-03-11 16:20:36 +0000 | [diff] [blame] | 493 | tlb->V1 = (env->CP0_EntryLo1 & 2) != 0; |
| 494 | tlb->D1 = (env->CP0_EntryLo1 & 4) != 0; |
| 495 | tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 496 | tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; |
| 497 | } |
| 498 | |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 499 | void r4k_do_tlbwi (void) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 500 | { |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 501 | /* Discard cached TLB entries. We could avoid doing this if the |
| 502 | tlbwi is just upgrading access permissions on the current entry; |
| 503 | that might be a further win. */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 504 | r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb); |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 505 | |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 506 | r4k_invalidate_tlb(env, env->CP0_Index % env->tlb->nb_tlb, 0); |
| 507 | r4k_fill_tlb(env->CP0_Index % env->tlb->nb_tlb); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 508 | } |
| 509 | |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 510 | void r4k_do_tlbwr (void) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 511 | { |
| 512 | int r = cpu_mips_get_random(env); |
| 513 | |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 514 | r4k_invalidate_tlb(env, r, 1); |
| 515 | r4k_fill_tlb(r); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 516 | } |
| 517 | |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 518 | void r4k_do_tlbp (void) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 519 | { |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 520 | r4k_tlb_t *tlb; |
ths | f2e9ebe | 2007-05-13 14:07:26 +0000 | [diff] [blame] | 521 | target_ulong mask; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 522 | target_ulong tag; |
ths | f2e9ebe | 2007-05-13 14:07:26 +0000 | [diff] [blame] | 523 | target_ulong VPN; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 524 | uint8_t ASID; |
| 525 | int i; |
| 526 | |
bellard | 3d9fb9fe | 2006-05-22 22:13:29 +0000 | [diff] [blame] | 527 | ASID = env->CP0_EntryHi & 0xFF; |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 528 | for (i = 0; i < env->tlb->nb_tlb; i++) { |
| 529 | tlb = &env->tlb->mmu.r4k.tlb[i]; |
ths | f2e9ebe | 2007-05-13 14:07:26 +0000 | [diff] [blame] | 530 | /* 1k pages are not supported. */ |
| 531 | mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); |
| 532 | tag = env->CP0_EntryHi & ~mask; |
| 533 | VPN = tlb->VPN & ~mask; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 534 | /* Check ASID, virtual page number & size */ |
ths | f2e9ebe | 2007-05-13 14:07:26 +0000 | [diff] [blame] | 535 | if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 536 | /* TLB match */ |
ths | 9c2149c | 2007-01-23 22:45:22 +0000 | [diff] [blame] | 537 | env->CP0_Index = i; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 538 | break; |
| 539 | } |
| 540 | } |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 541 | if (i == env->tlb->nb_tlb) { |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 542 | /* No match. Discard any shadow entries, if any of them match. */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 543 | for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) { |
| 544 | tlb = &env->tlb->mmu.r4k.tlb[i]; |
ths | f2e9ebe | 2007-05-13 14:07:26 +0000 | [diff] [blame] | 545 | /* 1k pages are not supported. */ |
| 546 | mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); |
| 547 | tag = env->CP0_EntryHi & ~mask; |
| 548 | VPN = tlb->VPN & ~mask; |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 549 | /* Check ASID, virtual page number & size */ |
ths | f2e9ebe | 2007-05-13 14:07:26 +0000 | [diff] [blame] | 550 | if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 551 | r4k_mips_tlb_flush_extra (env, i); |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 552 | break; |
| 553 | } |
| 554 | } |
| 555 | |
ths | 9c2149c | 2007-01-23 22:45:22 +0000 | [diff] [blame] | 556 | env->CP0_Index |= 0x80000000; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 557 | } |
| 558 | } |
| 559 | |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 560 | void r4k_do_tlbr (void) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 561 | { |
ths | 29929e3 | 2007-05-13 13:49:44 +0000 | [diff] [blame] | 562 | r4k_tlb_t *tlb; |
pbrook | 09c56b8 | 2006-03-11 16:39:23 +0000 | [diff] [blame] | 563 | uint8_t ASID; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 564 | |
pbrook | 09c56b8 | 2006-03-11 16:39:23 +0000 | [diff] [blame] | 565 | ASID = env->CP0_EntryHi & 0xFF; |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 566 | tlb = &env->tlb->mmu.r4k.tlb[env->CP0_Index % env->tlb->nb_tlb]; |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 567 | |
| 568 | /* If this will change the current ASID, flush qemu's TLB. */ |
ths | 814b9a4 | 2006-12-06 17:42:40 +0000 | [diff] [blame] | 569 | if (ASID != tlb->ASID) |
| 570 | cpu_mips_tlb_flush (env, 1); |
| 571 | |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 572 | r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 573 | |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 574 | env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
ths | 3b1c8be | 2007-01-22 20:50:42 +0000 | [diff] [blame] | 575 | env->CP0_PageMask = tlb->PageMask; |
ths | 7495fd0 | 2007-01-01 20:32:08 +0000 | [diff] [blame] | 576 | env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | |
| 577 | (tlb->C0 << 3) | (tlb->PFN[0] >> 6); |
| 578 | env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | |
| 579 | (tlb->C1 << 3) | (tlb->PFN[1] >> 6); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 580 | } |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 581 | |
bellard | 048f6b4 | 2005-11-26 18:47:20 +0000 | [diff] [blame] | 582 | #endif /* !CONFIG_USER_ONLY */ |
| 583 | |
ths | c570fd1 | 2006-12-21 01:19:56 +0000 | [diff] [blame] | 584 | void dump_ldst (const unsigned char *func) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 585 | { |
| 586 | if (loglevel) |
ths | 3594c77 | 2007-02-20 23:37:21 +0000 | [diff] [blame] | 587 | fprintf(logfile, "%s => " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__, T0, T1); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 588 | } |
| 589 | |
| 590 | void dump_sc (void) |
| 591 | { |
| 592 | if (loglevel) { |
ths | 3594c77 | 2007-02-20 23:37:21 +0000 | [diff] [blame] | 593 | fprintf(logfile, "%s " TARGET_FMT_lx " at " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", __func__, |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 594 | T1, T0, env->CP0_LLAddr); |
| 595 | } |
| 596 | } |
| 597 | |
ths | f41c52f | 2007-04-06 18:46:01 +0000 | [diff] [blame] | 598 | void debug_pre_eret (void) |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 599 | { |
ths | f41c52f | 2007-04-06 18:46:01 +0000 | [diff] [blame] | 600 | fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 601 | env->PC[env->current_tc], env->CP0_EPC); |
ths | f41c52f | 2007-04-06 18:46:01 +0000 | [diff] [blame] | 602 | if (env->CP0_Status & (1 << CP0St_ERL)) |
| 603 | fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); |
| 604 | if (env->hflags & MIPS_HFLAG_DM) |
| 605 | fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC); |
| 606 | fputs("\n", logfile); |
| 607 | } |
| 608 | |
| 609 | void debug_post_eret (void) |
| 610 | { |
ths | 744e091 | 2007-04-13 22:30:36 +0000 | [diff] [blame] | 611 | fprintf(logfile, " => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 612 | env->PC[env->current_tc], env->CP0_EPC); |
ths | f41c52f | 2007-04-06 18:46:01 +0000 | [diff] [blame] | 613 | if (env->CP0_Status & (1 << CP0St_ERL)) |
| 614 | fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); |
| 615 | if (env->hflags & MIPS_HFLAG_DM) |
| 616 | fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC); |
ths | 623a930 | 2007-10-28 19:45:05 +0000 | [diff] [blame] | 617 | switch (env->hflags & MIPS_HFLAG_KSU) { |
| 618 | case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break; |
| 619 | case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break; |
| 620 | case MIPS_HFLAG_KM: fputs("\n", logfile); break; |
| 621 | default: cpu_abort(env, "Invalid MMU mode!\n"); break; |
| 622 | } |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 623 | } |
| 624 | |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 625 | void do_pmon (int function) |
| 626 | { |
| 627 | function /= 2; |
| 628 | switch (function) { |
| 629 | case 2: /* TODO: char inbyte(int waitflag); */ |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 630 | if (env->gpr[env->current_tc][4] == 0) |
| 631 | env->gpr[env->current_tc][2] = -1; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 632 | /* Fall through */ |
| 633 | case 11: /* TODO: char inbyte (void); */ |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 634 | env->gpr[env->current_tc][2] = -1; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 635 | break; |
| 636 | case 3: |
| 637 | case 12: |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 638 | printf("%c", (char)(env->gpr[env->current_tc][4] & 0xFF)); |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 639 | break; |
| 640 | case 17: |
| 641 | break; |
| 642 | case 158: |
| 643 | { |
ths | d0dc7dc | 2008-02-12 21:01:26 +0000 | [diff] [blame] | 644 | unsigned char *fmt = (void *)(unsigned long)env->gpr[env->current_tc][4]; |
bellard | 6af0bf9 | 2005-07-02 14:58:51 +0000 | [diff] [blame] | 645 | printf("%s", fmt); |
| 646 | } |
| 647 | break; |
| 648 | } |
| 649 | } |
bellard | e37e863 | 2005-07-04 22:17:33 +0000 | [diff] [blame] | 650 | |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 651 | #if !defined(CONFIG_USER_ONLY) |
bellard | e37e863 | 2005-07-04 22:17:33 +0000 | [diff] [blame] | 652 | |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 653 | static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr); |
| 654 | |
bellard | e37e863 | 2005-07-04 22:17:33 +0000 | [diff] [blame] | 655 | #define MMUSUFFIX _mmu |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 656 | #define ALIGNED_ONLY |
bellard | e37e863 | 2005-07-04 22:17:33 +0000 | [diff] [blame] | 657 | |
| 658 | #define SHIFT 0 |
| 659 | #include "softmmu_template.h" |
| 660 | |
| 661 | #define SHIFT 1 |
| 662 | #include "softmmu_template.h" |
| 663 | |
| 664 | #define SHIFT 2 |
| 665 | #include "softmmu_template.h" |
| 666 | |
| 667 | #define SHIFT 3 |
| 668 | #include "softmmu_template.h" |
| 669 | |
bellard | 4ad40f3 | 2005-12-05 19:59:36 +0000 | [diff] [blame] | 670 | static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr) |
| 671 | { |
| 672 | env->CP0_BadVAddr = addr; |
| 673 | do_restore_state (retaddr); |
| 674 | do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL); |
| 675 | } |
| 676 | |
j_mayer | 6ebbf39 | 2007-10-14 07:07:08 +0000 | [diff] [blame] | 677 | void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
bellard | e37e863 | 2005-07-04 22:17:33 +0000 | [diff] [blame] | 678 | { |
| 679 | TranslationBlock *tb; |
| 680 | CPUState *saved_env; |
| 681 | unsigned long pc; |
| 682 | int ret; |
| 683 | |
| 684 | /* XXX: hack to restore env in all cases, even if not called from |
| 685 | generated code */ |
| 686 | saved_env = env; |
| 687 | env = cpu_single_env; |
j_mayer | 6ebbf39 | 2007-10-14 07:07:08 +0000 | [diff] [blame] | 688 | ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); |
bellard | e37e863 | 2005-07-04 22:17:33 +0000 | [diff] [blame] | 689 | if (ret) { |
| 690 | if (retaddr) { |
| 691 | /* now we have a real cpu fault */ |
| 692 | pc = (unsigned long)retaddr; |
| 693 | tb = tb_find_pc(pc); |
| 694 | if (tb) { |
| 695 | /* the PC is inside the translated code. It means that we have |
| 696 | a virtual CPU fault */ |
| 697 | cpu_restore_state(tb, env, pc, NULL); |
| 698 | } |
| 699 | } |
| 700 | do_raise_exception_err(env->exception_index, env->error_code); |
| 701 | } |
| 702 | env = saved_env; |
| 703 | } |
| 704 | |
ths | 647de6c | 2007-10-20 19:45:44 +0000 | [diff] [blame] | 705 | void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, |
| 706 | int unused) |
| 707 | { |
| 708 | if (is_exec) |
| 709 | do_raise_exception(EXCP_IBE); |
| 710 | else |
| 711 | do_raise_exception(EXCP_DBE); |
| 712 | } |
bellard | e37e863 | 2005-07-04 22:17:33 +0000 | [diff] [blame] | 713 | #endif |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 714 | |
| 715 | /* Complex FPU operations which may need stack space. */ |
| 716 | |
pbrook | f090c9d | 2007-11-18 14:33:24 +0000 | [diff] [blame] | 717 | #define FLOAT_ONE32 make_float32(0x3f8 << 20) |
| 718 | #define FLOAT_ONE64 make_float64(0x3ffULL << 52) |
| 719 | #define FLOAT_TWO32 make_float32(1 << 30) |
| 720 | #define FLOAT_TWO64 make_float64(1ULL << 62) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 721 | #define FLOAT_QNAN32 0x7fbfffff |
| 722 | #define FLOAT_QNAN64 0x7ff7ffffffffffffULL |
| 723 | #define FLOAT_SNAN32 0x7fffffff |
| 724 | #define FLOAT_SNAN64 0x7fffffffffffffffULL |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 725 | |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 726 | /* convert MIPS rounding mode in FCR31 to IEEE library */ |
| 727 | unsigned int ieee_rm[] = { |
| 728 | float_round_nearest_even, |
| 729 | float_round_to_zero, |
| 730 | float_round_up, |
| 731 | float_round_down |
| 732 | }; |
| 733 | |
| 734 | #define RESTORE_ROUNDING_MODE \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 735 | set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 736 | |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 737 | void do_cfc1 (int reg) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 738 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 739 | switch (reg) { |
| 740 | case 0: |
| 741 | T0 = (int32_t)env->fpu->fcr0; |
| 742 | break; |
| 743 | case 25: |
| 744 | T0 = ((env->fpu->fcr31 >> 24) & 0xfe) | ((env->fpu->fcr31 >> 23) & 0x1); |
| 745 | break; |
| 746 | case 26: |
| 747 | T0 = env->fpu->fcr31 & 0x0003f07c; |
| 748 | break; |
| 749 | case 28: |
| 750 | T0 = (env->fpu->fcr31 & 0x00000f83) | ((env->fpu->fcr31 >> 22) & 0x4); |
| 751 | break; |
| 752 | default: |
| 753 | T0 = (int32_t)env->fpu->fcr31; |
| 754 | break; |
| 755 | } |
| 756 | } |
| 757 | |
| 758 | void do_ctc1 (int reg) |
| 759 | { |
| 760 | switch(reg) { |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 761 | case 25: |
| 762 | if (T0 & 0xffffff00) |
| 763 | return; |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 764 | env->fpu->fcr31 = (env->fpu->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) | |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 765 | ((T0 & 0x1) << 23); |
| 766 | break; |
| 767 | case 26: |
| 768 | if (T0 & 0x007c0000) |
| 769 | return; |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 770 | env->fpu->fcr31 = (env->fpu->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 771 | break; |
| 772 | case 28: |
| 773 | if (T0 & 0x007c0000) |
| 774 | return; |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 775 | env->fpu->fcr31 = (env->fpu->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) | |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 776 | ((T0 & 0x4) << 22); |
| 777 | break; |
| 778 | case 31: |
| 779 | if (T0 & 0x007c0000) |
| 780 | return; |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 781 | env->fpu->fcr31 = T0; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 782 | break; |
| 783 | default: |
| 784 | return; |
| 785 | } |
| 786 | /* set rounding mode */ |
| 787 | RESTORE_ROUNDING_MODE; |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 788 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 789 | if ((GET_FP_ENABLE(env->fpu->fcr31) | 0x20) & GET_FP_CAUSE(env->fpu->fcr31)) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 790 | do_raise_exception(EXCP_FPE); |
| 791 | } |
| 792 | |
ths | aa34373 | 2007-10-09 03:39:58 +0000 | [diff] [blame] | 793 | static always_inline char ieee_ex_to_mips(char xcpt) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 794 | { |
| 795 | return (xcpt & float_flag_inexact) >> 5 | |
| 796 | (xcpt & float_flag_underflow) >> 3 | |
| 797 | (xcpt & float_flag_overflow) >> 1 | |
| 798 | (xcpt & float_flag_divbyzero) << 1 | |
| 799 | (xcpt & float_flag_invalid) << 4; |
| 800 | } |
| 801 | |
ths | aa34373 | 2007-10-09 03:39:58 +0000 | [diff] [blame] | 802 | static always_inline char mips_ex_to_ieee(char xcpt) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 803 | { |
| 804 | return (xcpt & FP_INEXACT) << 5 | |
| 805 | (xcpt & FP_UNDERFLOW) << 3 | |
| 806 | (xcpt & FP_OVERFLOW) << 1 | |
| 807 | (xcpt & FP_DIV0) >> 1 | |
| 808 | (xcpt & FP_INVALID) >> 4; |
| 809 | } |
| 810 | |
ths | aa34373 | 2007-10-09 03:39:58 +0000 | [diff] [blame] | 811 | static always_inline void update_fcr31(void) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 812 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 813 | int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fpu->fp_status)); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 814 | |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 815 | SET_FP_CAUSE(env->fpu->fcr31, tmp); |
| 816 | if (GET_FP_ENABLE(env->fpu->fcr31) & tmp) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 817 | do_raise_exception(EXCP_FPE); |
| 818 | else |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 819 | UPDATE_FP_FLAGS(env->fpu->fcr31, tmp); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 820 | } |
| 821 | |
| 822 | #define FLOAT_OP(name, p) void do_float_##name##_##p(void) |
| 823 | |
| 824 | FLOAT_OP(cvtd, s) |
| 825 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 826 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 827 | FDT2 = float32_to_float64(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 828 | update_fcr31(); |
| 829 | } |
| 830 | FLOAT_OP(cvtd, w) |
| 831 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 832 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 833 | FDT2 = int32_to_float64(WT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 834 | update_fcr31(); |
| 835 | } |
| 836 | FLOAT_OP(cvtd, l) |
| 837 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 838 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 839 | FDT2 = int64_to_float64(DT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 840 | update_fcr31(); |
| 841 | } |
| 842 | FLOAT_OP(cvtl, d) |
| 843 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 844 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 845 | DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 846 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 847 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 848 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 849 | } |
| 850 | FLOAT_OP(cvtl, s) |
| 851 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 852 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 853 | DT2 = float32_to_int64(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 854 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 855 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 856 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 857 | } |
| 858 | |
| 859 | FLOAT_OP(cvtps, pw) |
| 860 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 861 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 862 | FST2 = int32_to_float32(WT0, &env->fpu->fp_status); |
| 863 | FSTH2 = int32_to_float32(WTH0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 864 | update_fcr31(); |
| 865 | } |
| 866 | FLOAT_OP(cvtpw, ps) |
| 867 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 868 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 869 | WT2 = float32_to_int32(FST0, &env->fpu->fp_status); |
| 870 | WTH2 = float32_to_int32(FSTH0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 871 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 872 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 873 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 874 | } |
| 875 | FLOAT_OP(cvts, d) |
| 876 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 877 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 878 | FST2 = float64_to_float32(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 879 | update_fcr31(); |
| 880 | } |
| 881 | FLOAT_OP(cvts, w) |
| 882 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 883 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 884 | FST2 = int32_to_float32(WT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 885 | update_fcr31(); |
| 886 | } |
| 887 | FLOAT_OP(cvts, l) |
| 888 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 889 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 890 | FST2 = int64_to_float32(DT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 891 | update_fcr31(); |
| 892 | } |
| 893 | FLOAT_OP(cvts, pl) |
| 894 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 895 | set_float_exception_flags(0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 896 | WT2 = WT0; |
| 897 | update_fcr31(); |
| 898 | } |
| 899 | FLOAT_OP(cvts, pu) |
| 900 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 901 | set_float_exception_flags(0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 902 | WT2 = WTH0; |
| 903 | update_fcr31(); |
| 904 | } |
| 905 | FLOAT_OP(cvtw, s) |
| 906 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 907 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 908 | WT2 = float32_to_int32(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 909 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 910 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 911 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 912 | } |
| 913 | FLOAT_OP(cvtw, d) |
| 914 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 915 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 916 | WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 917 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 918 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 919 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 920 | } |
| 921 | |
| 922 | FLOAT_OP(roundl, d) |
| 923 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 924 | set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); |
| 925 | DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 926 | RESTORE_ROUNDING_MODE; |
| 927 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 928 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 929 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 930 | } |
| 931 | FLOAT_OP(roundl, s) |
| 932 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 933 | set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); |
| 934 | DT2 = float32_to_int64(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 935 | RESTORE_ROUNDING_MODE; |
| 936 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 937 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 938 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 939 | } |
| 940 | FLOAT_OP(roundw, d) |
| 941 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 942 | set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); |
| 943 | WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 944 | RESTORE_ROUNDING_MODE; |
| 945 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 946 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 947 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 948 | } |
| 949 | FLOAT_OP(roundw, s) |
| 950 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 951 | set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); |
| 952 | WT2 = float32_to_int32(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 953 | RESTORE_ROUNDING_MODE; |
| 954 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 955 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 956 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 957 | } |
| 958 | |
| 959 | FLOAT_OP(truncl, d) |
| 960 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 961 | DT2 = float64_to_int64_round_to_zero(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 962 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 963 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 964 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 965 | } |
| 966 | FLOAT_OP(truncl, s) |
| 967 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 968 | DT2 = float32_to_int64_round_to_zero(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 969 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 970 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 971 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 972 | } |
| 973 | FLOAT_OP(truncw, d) |
| 974 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 975 | WT2 = float64_to_int32_round_to_zero(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 976 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 977 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 978 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 979 | } |
| 980 | FLOAT_OP(truncw, s) |
| 981 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 982 | WT2 = float32_to_int32_round_to_zero(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 983 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 984 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 985 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 986 | } |
| 987 | |
| 988 | FLOAT_OP(ceill, d) |
| 989 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 990 | set_float_rounding_mode(float_round_up, &env->fpu->fp_status); |
| 991 | DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 992 | RESTORE_ROUNDING_MODE; |
| 993 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 994 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 995 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 996 | } |
| 997 | FLOAT_OP(ceill, s) |
| 998 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 999 | set_float_rounding_mode(float_round_up, &env->fpu->fp_status); |
| 1000 | DT2 = float32_to_int64(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1001 | RESTORE_ROUNDING_MODE; |
| 1002 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1003 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 1004 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1005 | } |
| 1006 | FLOAT_OP(ceilw, d) |
| 1007 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1008 | set_float_rounding_mode(float_round_up, &env->fpu->fp_status); |
| 1009 | WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1010 | RESTORE_ROUNDING_MODE; |
| 1011 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1012 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 1013 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1014 | } |
| 1015 | FLOAT_OP(ceilw, s) |
| 1016 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1017 | set_float_rounding_mode(float_round_up, &env->fpu->fp_status); |
| 1018 | WT2 = float32_to_int32(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1019 | RESTORE_ROUNDING_MODE; |
| 1020 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1021 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 1022 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1023 | } |
| 1024 | |
| 1025 | FLOAT_OP(floorl, d) |
| 1026 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1027 | set_float_rounding_mode(float_round_down, &env->fpu->fp_status); |
| 1028 | DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1029 | RESTORE_ROUNDING_MODE; |
| 1030 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1031 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 1032 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1033 | } |
| 1034 | FLOAT_OP(floorl, s) |
| 1035 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1036 | set_float_rounding_mode(float_round_down, &env->fpu->fp_status); |
| 1037 | DT2 = float32_to_int64(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1038 | RESTORE_ROUNDING_MODE; |
| 1039 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1040 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 1041 | DT2 = FLOAT_SNAN64; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1042 | } |
| 1043 | FLOAT_OP(floorw, d) |
| 1044 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1045 | set_float_rounding_mode(float_round_down, &env->fpu->fp_status); |
| 1046 | WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1047 | RESTORE_ROUNDING_MODE; |
| 1048 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1049 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 1050 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1051 | } |
| 1052 | FLOAT_OP(floorw, s) |
| 1053 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1054 | set_float_rounding_mode(float_round_down, &env->fpu->fp_status); |
| 1055 | WT2 = float32_to_int32(FST0, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1056 | RESTORE_ROUNDING_MODE; |
| 1057 | update_fcr31(); |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1058 | if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
ths | 5445409 | 2007-09-29 19:19:59 +0000 | [diff] [blame] | 1059 | WT2 = FLOAT_SNAN32; |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1060 | } |
| 1061 | |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1062 | /* MIPS specific unary operations */ |
| 1063 | FLOAT_OP(recip, d) |
| 1064 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1065 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1066 | FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1067 | update_fcr31(); |
ths | 57fa1fb | 2007-05-19 20:29:41 +0000 | [diff] [blame] | 1068 | } |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1069 | FLOAT_OP(recip, s) |
| 1070 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1071 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1072 | FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1073 | update_fcr31(); |
| 1074 | } |
ths | 57fa1fb | 2007-05-19 20:29:41 +0000 | [diff] [blame] | 1075 | |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1076 | FLOAT_OP(rsqrt, d) |
| 1077 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1078 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1079 | FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status); |
| 1080 | FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1081 | update_fcr31(); |
ths | 57fa1fb | 2007-05-19 20:29:41 +0000 | [diff] [blame] | 1082 | } |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1083 | FLOAT_OP(rsqrt, s) |
| 1084 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1085 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1086 | FST2 = float32_sqrt(FST0, &env->fpu->fp_status); |
| 1087 | FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1088 | update_fcr31(); |
| 1089 | } |
| 1090 | |
| 1091 | FLOAT_OP(recip1, d) |
| 1092 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1093 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1094 | FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1095 | update_fcr31(); |
| 1096 | } |
| 1097 | FLOAT_OP(recip1, s) |
| 1098 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1099 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1100 | FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1101 | update_fcr31(); |
| 1102 | } |
| 1103 | FLOAT_OP(recip1, ps) |
| 1104 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1105 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1106 | FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status); |
| 1107 | FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1108 | update_fcr31(); |
| 1109 | } |
| 1110 | |
| 1111 | FLOAT_OP(rsqrt1, d) |
| 1112 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1113 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1114 | FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status); |
| 1115 | FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1116 | update_fcr31(); |
| 1117 | } |
| 1118 | FLOAT_OP(rsqrt1, s) |
| 1119 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1120 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1121 | FST2 = float32_sqrt(FST0, &env->fpu->fp_status); |
| 1122 | FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1123 | update_fcr31(); |
| 1124 | } |
| 1125 | FLOAT_OP(rsqrt1, ps) |
| 1126 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1127 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1128 | FST2 = float32_sqrt(FST0, &env->fpu->fp_status); |
| 1129 | FSTH2 = float32_sqrt(FSTH0, &env->fpu->fp_status); |
| 1130 | FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status); |
| 1131 | FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fpu->fp_status); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1132 | update_fcr31(); |
| 1133 | } |
ths | 57fa1fb | 2007-05-19 20:29:41 +0000 | [diff] [blame] | 1134 | |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1135 | /* binary operations */ |
| 1136 | #define FLOAT_BINOP(name) \ |
| 1137 | FLOAT_OP(name, d) \ |
| 1138 | { \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1139 | set_float_exception_flags(0, &env->fpu->fp_status); \ |
| 1140 | FDT2 = float64_ ## name (FDT0, FDT1, &env->fpu->fp_status); \ |
| 1141 | update_fcr31(); \ |
| 1142 | if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \ |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1143 | DT2 = FLOAT_QNAN64; \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1144 | } \ |
| 1145 | FLOAT_OP(name, s) \ |
| 1146 | { \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1147 | set_float_exception_flags(0, &env->fpu->fp_status); \ |
| 1148 | FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status); \ |
| 1149 | update_fcr31(); \ |
| 1150 | if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \ |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1151 | WT2 = FLOAT_QNAN32; \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1152 | } \ |
| 1153 | FLOAT_OP(name, ps) \ |
| 1154 | { \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1155 | set_float_exception_flags(0, &env->fpu->fp_status); \ |
| 1156 | FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status); \ |
| 1157 | FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fpu->fp_status); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1158 | update_fcr31(); \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1159 | if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) { \ |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1160 | WT2 = FLOAT_QNAN32; \ |
| 1161 | WTH2 = FLOAT_QNAN32; \ |
ths | 3a5b360 | 2007-05-20 13:27:58 +0000 | [diff] [blame] | 1162 | } \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1163 | } |
| 1164 | FLOAT_BINOP(add) |
| 1165 | FLOAT_BINOP(sub) |
| 1166 | FLOAT_BINOP(mul) |
| 1167 | FLOAT_BINOP(div) |
| 1168 | #undef FLOAT_BINOP |
| 1169 | |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1170 | /* MIPS specific binary operations */ |
| 1171 | FLOAT_OP(recip2, d) |
| 1172 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1173 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1174 | FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status); |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1175 | FDT2 = float64_chs(float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status)); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1176 | update_fcr31(); |
ths | 57fa1fb | 2007-05-19 20:29:41 +0000 | [diff] [blame] | 1177 | } |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1178 | FLOAT_OP(recip2, s) |
| 1179 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1180 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1181 | FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1182 | FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status)); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1183 | update_fcr31(); |
| 1184 | } |
| 1185 | FLOAT_OP(recip2, ps) |
| 1186 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1187 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1188 | FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); |
| 1189 | FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status); |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1190 | FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status)); |
| 1191 | FSTH2 = float32_chs(float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status)); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1192 | update_fcr31(); |
| 1193 | } |
| 1194 | |
| 1195 | FLOAT_OP(rsqrt2, d) |
| 1196 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1197 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1198 | FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status); |
| 1199 | FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status); |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1200 | FDT2 = float64_chs(float64_div(FDT2, FLOAT_TWO64, &env->fpu->fp_status)); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1201 | update_fcr31(); |
| 1202 | } |
| 1203 | FLOAT_OP(rsqrt2, s) |
| 1204 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1205 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1206 | FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); |
| 1207 | FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status); |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1208 | FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status)); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1209 | update_fcr31(); |
| 1210 | } |
| 1211 | FLOAT_OP(rsqrt2, ps) |
| 1212 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1213 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1214 | FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); |
| 1215 | FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status); |
| 1216 | FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status); |
| 1217 | FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status); |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1218 | FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status)); |
| 1219 | FSTH2 = float32_chs(float32_div(FSTH2, FLOAT_TWO32, &env->fpu->fp_status)); |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1220 | update_fcr31(); |
| 1221 | } |
ths | 57fa1fb | 2007-05-19 20:29:41 +0000 | [diff] [blame] | 1222 | |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1223 | FLOAT_OP(addr, ps) |
| 1224 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1225 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1226 | FST2 = float32_add (FST0, FSTH0, &env->fpu->fp_status); |
| 1227 | FSTH2 = float32_add (FST1, FSTH1, &env->fpu->fp_status); |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1228 | update_fcr31(); |
| 1229 | } |
| 1230 | |
ths | 57fa1fb | 2007-05-19 20:29:41 +0000 | [diff] [blame] | 1231 | FLOAT_OP(mulr, ps) |
| 1232 | { |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1233 | set_float_exception_flags(0, &env->fpu->fp_status); |
| 1234 | FST2 = float32_mul (FST0, FSTH0, &env->fpu->fp_status); |
| 1235 | FSTH2 = float32_mul (FST1, FSTH1, &env->fpu->fp_status); |
ths | 57fa1fb | 2007-05-19 20:29:41 +0000 | [diff] [blame] | 1236 | update_fcr31(); |
| 1237 | } |
| 1238 | |
ths | 8dfdb87 | 2007-06-26 20:26:03 +0000 | [diff] [blame] | 1239 | /* compare operations */ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1240 | #define FOP_COND_D(op, cond) \ |
| 1241 | void do_cmp_d_ ## op (long cc) \ |
| 1242 | { \ |
| 1243 | int c = cond; \ |
| 1244 | update_fcr31(); \ |
| 1245 | if (c) \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1246 | SET_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1247 | else \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1248 | CLEAR_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1249 | } \ |
| 1250 | void do_cmpabs_d_ ## op (long cc) \ |
| 1251 | { \ |
| 1252 | int c; \ |
ths | 6b5435d | 2008-01-08 18:11:08 +0000 | [diff] [blame] | 1253 | FDT0 = float64_abs(FDT0); \ |
| 1254 | FDT1 = float64_abs(FDT1); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1255 | c = cond; \ |
| 1256 | update_fcr31(); \ |
| 1257 | if (c) \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1258 | SET_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1259 | else \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1260 | CLEAR_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1261 | } |
| 1262 | |
| 1263 | int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) |
| 1264 | { |
| 1265 | if (float64_is_signaling_nan(a) || |
| 1266 | float64_is_signaling_nan(b) || |
| 1267 | (sig && (float64_is_nan(a) || float64_is_nan(b)))) { |
| 1268 | float_raise(float_flag_invalid, status); |
| 1269 | return 1; |
| 1270 | } else if (float64_is_nan(a) || float64_is_nan(b)) { |
| 1271 | return 1; |
| 1272 | } else { |
| 1273 | return 0; |
| 1274 | } |
| 1275 | } |
| 1276 | |
| 1277 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1278 | * but float*_is_unordered() is still called. */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1279 | FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status), 0)) |
| 1280 | FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status)) |
| 1281 | FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status)) |
| 1282 | FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_eq(FDT0, FDT1, &env->fpu->fp_status)) |
| 1283 | FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status)) |
| 1284 | FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_lt(FDT0, FDT1, &env->fpu->fp_status)) |
| 1285 | FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status)) |
| 1286 | FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_le(FDT0, FDT1, &env->fpu->fp_status)) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1287 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1288 | * but float*_is_unordered() is still called. */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1289 | FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status), 0)) |
| 1290 | FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status)) |
| 1291 | FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status)) |
| 1292 | FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_eq(FDT0, FDT1, &env->fpu->fp_status)) |
| 1293 | FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status)) |
| 1294 | FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_lt(FDT0, FDT1, &env->fpu->fp_status)) |
| 1295 | FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status)) |
| 1296 | FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_le(FDT0, FDT1, &env->fpu->fp_status)) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1297 | |
| 1298 | #define FOP_COND_S(op, cond) \ |
| 1299 | void do_cmp_s_ ## op (long cc) \ |
| 1300 | { \ |
| 1301 | int c = cond; \ |
| 1302 | update_fcr31(); \ |
| 1303 | if (c) \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1304 | SET_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1305 | else \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1306 | CLEAR_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1307 | } \ |
| 1308 | void do_cmpabs_s_ ## op (long cc) \ |
| 1309 | { \ |
| 1310 | int c; \ |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1311 | FST0 = float32_abs(FST0); \ |
| 1312 | FST1 = float32_abs(FST1); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1313 | c = cond; \ |
| 1314 | update_fcr31(); \ |
| 1315 | if (c) \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1316 | SET_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1317 | else \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1318 | CLEAR_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1319 | } |
| 1320 | |
| 1321 | flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) |
| 1322 | { |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1323 | if (float32_is_signaling_nan(a) || |
| 1324 | float32_is_signaling_nan(b) || |
| 1325 | (sig && (float32_is_nan(a) || float32_is_nan(b)))) { |
| 1326 | float_raise(float_flag_invalid, status); |
| 1327 | return 1; |
| 1328 | } else if (float32_is_nan(a) || float32_is_nan(b)) { |
| 1329 | return 1; |
| 1330 | } else { |
| 1331 | return 0; |
| 1332 | } |
| 1333 | } |
| 1334 | |
| 1335 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1336 | * but float*_is_unordered() is still called. */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1337 | FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0)) |
| 1338 | FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)) |
| 1339 | FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status)) |
| 1340 | FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status)) |
| 1341 | FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status)) |
| 1342 | FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status)) |
| 1343 | FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status)) |
| 1344 | FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status)) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1345 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1346 | * but float*_is_unordered() is still called. */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1347 | FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0)) |
| 1348 | FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)) |
| 1349 | FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status)) |
| 1350 | FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status)) |
| 1351 | FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status)) |
| 1352 | FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status)) |
| 1353 | FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status)) |
| 1354 | FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status)) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1355 | |
| 1356 | #define FOP_COND_PS(op, condl, condh) \ |
| 1357 | void do_cmp_ps_ ## op (long cc) \ |
| 1358 | { \ |
| 1359 | int cl = condl; \ |
| 1360 | int ch = condh; \ |
| 1361 | update_fcr31(); \ |
| 1362 | if (cl) \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1363 | SET_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1364 | else \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1365 | CLEAR_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1366 | if (ch) \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1367 | SET_FP_COND(cc + 1, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1368 | else \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1369 | CLEAR_FP_COND(cc + 1, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1370 | } \ |
| 1371 | void do_cmpabs_ps_ ## op (long cc) \ |
| 1372 | { \ |
| 1373 | int cl, ch; \ |
pbrook | 5747c07 | 2007-11-17 14:53:06 +0000 | [diff] [blame] | 1374 | FST0 = float32_abs(FST0); \ |
| 1375 | FSTH0 = float32_abs(FSTH0); \ |
| 1376 | FST1 = float32_abs(FST1); \ |
| 1377 | FSTH1 = float32_abs(FSTH1); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1378 | cl = condl; \ |
| 1379 | ch = condh; \ |
| 1380 | update_fcr31(); \ |
| 1381 | if (cl) \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1382 | SET_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1383 | else \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1384 | CLEAR_FP_COND(cc, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1385 | if (ch) \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1386 | SET_FP_COND(cc + 1, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1387 | else \ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1388 | CLEAR_FP_COND(cc + 1, env->fpu); \ |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1389 | } |
| 1390 | |
| 1391 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1392 | * but float*_is_unordered() is still called. */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1393 | FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0), |
| 1394 | (float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status), 0)) |
| 1395 | FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), |
| 1396 | float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status)) |
| 1397 | FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status), |
| 1398 | !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1399 | FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status), |
| 1400 | float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1401 | FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status), |
| 1402 | !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1403 | FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status), |
| 1404 | float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1405 | FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status), |
| 1406 | !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1407 | FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status), |
| 1408 | float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) |
ths | fd4a04e | 2007-05-18 11:55:54 +0000 | [diff] [blame] | 1409 | /* NOTE: the comma operator will make "cond" to eval to false, |
| 1410 | * but float*_is_unordered() is still called. */ |
ths | ead9360 | 2007-09-06 00:18:15 +0000 | [diff] [blame] | 1411 | FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0), |
| 1412 | (float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status), 0)) |
| 1413 | FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), |
| 1414 | float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status)) |
| 1415 | FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status), |
| 1416 | !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1417 | FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status), |
| 1418 | float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1419 | FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status), |
| 1420 | !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1421 | FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status), |
| 1422 | float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1423 | FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status), |
| 1424 | !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) |
| 1425 | FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status), |
| 1426 | float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) |