|
|
1.1 root 1: /*
2: * MIPS emulation helpers for qemu.
1.1.1.6 root 3: *
1.1 root 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
1.1.1.7 ! root 18: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
1.1 root 19: */
1.1.1.6 root 20: #include <stdlib.h>
1.1 root 21: #include "exec.h"
22:
1.1.1.6 root 23: #include "host-utils.h"
1.1 root 24:
1.1.1.7 ! root 25: #include "helper.h"
1.1 root 26: /*****************************************************************************/
27: /* Exceptions processing helpers */
28:
29: void do_raise_exception_err (uint32_t exception, int error_code)
30: {
31: #if 1
1.1.1.7 ! root 32: if (exception < 0x100)
! 33: qemu_log("%s: %d %d\n", __func__, exception, error_code);
1.1 root 34: #endif
35: env->exception_index = exception;
36: env->error_code = error_code;
37: cpu_loop_exit();
38: }
39:
40: void do_raise_exception (uint32_t exception)
41: {
42: do_raise_exception_err(exception, 0);
43: }
44:
1.1.1.7 ! root 45: void do_interrupt_restart (void)
1.1.1.2 root 46: {
1.1.1.7 ! root 47: if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
! 48: !(env->CP0_Status & (1 << CP0St_ERL)) &&
! 49: !(env->hflags & MIPS_HFLAG_DM) &&
! 50: (env->CP0_Status & (1 << CP0St_IE)) &&
! 51: (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
! 52: env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
! 53: do_raise_exception(EXCP_EXT_INTERRUPT);
! 54: }
! 55: }
1.1.1.2 root 56:
1.1.1.7 ! root 57: #if !defined(CONFIG_USER_ONLY)
! 58: static void do_restore_state (void *pc_ptr)
! 59: {
! 60: TranslationBlock *tb;
! 61: unsigned long pc = (unsigned long) pc_ptr;
! 62:
! 63: tb = tb_find_pc (pc);
! 64: if (tb) {
! 65: cpu_restore_state (tb, env, pc, NULL);
! 66: }
1.1.1.2 root 67: }
1.1.1.7 ! root 68: #endif
1.1.1.2 root 69:
1.1.1.7 ! root 70: target_ulong do_clo (target_ulong t0)
1.1.1.2 root 71: {
1.1.1.7 ! root 72: return clo32(t0);
1.1.1.2 root 73: }
74:
1.1.1.7 ! root 75: target_ulong do_clz (target_ulong t0)
1.1.1.6 root 76: {
1.1.1.7 ! root 77: return clz32(t0);
1.1.1.6 root 78: }
1.1 root 79:
1.1.1.6 root 80: #if defined(TARGET_MIPS64)
1.1.1.7 ! root 81: target_ulong do_dclo (target_ulong t0)
! 82: {
! 83: return clo64(t0);
! 84: }
! 85:
! 86: target_ulong do_dclz (target_ulong t0)
! 87: {
! 88: return clz64(t0);
! 89: }
! 90: #endif /* TARGET_MIPS64 */
! 91:
! 92: /* 64 bits arithmetic for 32 bits hosts */
! 93: static inline uint64_t get_HILO (void)
! 94: {
! 95: return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0];
! 96: }
! 97:
! 98: static inline void set_HILO (uint64_t HILO)
! 99: {
! 100: env->active_tc.LO[0] = (int32_t)HILO;
! 101: env->active_tc.HI[0] = (int32_t)(HILO >> 32);
! 102: }
! 103:
! 104: static inline void set_HIT0_LO (target_ulong t0, uint64_t HILO)
! 105: {
! 106: env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
! 107: t0 = env->active_tc.HI[0] = (int32_t)(HILO >> 32);
! 108: }
! 109:
! 110: static inline void set_HI_LOT0 (target_ulong t0, uint64_t HILO)
! 111: {
! 112: t0 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
! 113: env->active_tc.HI[0] = (int32_t)(HILO >> 32);
! 114: }
! 115:
1.1.1.5 root 116: #if TARGET_LONG_BITS > HOST_LONG_BITS
1.1.1.7 ! root 117: void do_madd (target_ulong t0, target_ulong t1)
! 118: {
! 119: int64_t tmp;
! 120:
! 121: tmp = ((int64_t)(int32_t)t0 * (int64_t)(int32_t)t1);
! 122: set_HILO((int64_t)get_HILO() + tmp);
! 123: }
! 124:
! 125: void do_maddu (target_ulong t0, target_ulong t1)
! 126: {
! 127: uint64_t tmp;
! 128:
! 129: tmp = ((uint64_t)(uint32_t)t0 * (uint64_t)(uint32_t)t1);
! 130: set_HILO(get_HILO() + tmp);
! 131: }
! 132:
! 133: void do_msub (target_ulong t0, target_ulong t1)
! 134: {
! 135: int64_t tmp;
! 136:
! 137: tmp = ((int64_t)(int32_t)t0 * (int64_t)(int32_t)t1);
! 138: set_HILO((int64_t)get_HILO() - tmp);
! 139: }
! 140:
! 141: void do_msubu (target_ulong t0, target_ulong t1)
! 142: {
! 143: uint64_t tmp;
! 144:
! 145: tmp = ((uint64_t)(uint32_t)t0 * (uint64_t)(uint32_t)t1);
! 146: set_HILO(get_HILO() - tmp);
! 147: }
! 148: #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
! 149:
! 150: /* Multiplication variants of the vr54xx. */
! 151: target_ulong do_muls (target_ulong t0, target_ulong t1)
! 152: {
! 153: set_HI_LOT0(t0, 0 - ((int64_t)(int32_t)t0 * (int64_t)(int32_t)t1));
! 154:
! 155: return t0;
! 156: }
! 157:
! 158: target_ulong do_mulsu (target_ulong t0, target_ulong t1)
! 159: {
! 160: set_HI_LOT0(t0, 0 - ((uint64_t)(uint32_t)t0 * (uint64_t)(uint32_t)t1));
! 161:
! 162: return t0;
! 163: }
! 164:
! 165: target_ulong do_macc (target_ulong t0, target_ulong t1)
! 166: {
! 167: set_HI_LOT0(t0, ((int64_t)get_HILO()) + ((int64_t)(int32_t)t0 * (int64_t)(int32_t)t1));
! 168:
! 169: return t0;
! 170: }
! 171:
! 172: target_ulong do_macchi (target_ulong t0, target_ulong t1)
! 173: {
! 174: set_HIT0_LO(t0, ((int64_t)get_HILO()) + ((int64_t)(int32_t)t0 * (int64_t)(int32_t)t1));
! 175:
! 176: return t0;
! 177: }
! 178:
! 179: target_ulong do_maccu (target_ulong t0, target_ulong t1)
! 180: {
! 181: set_HI_LOT0(t0, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)t0 * (uint64_t)(uint32_t)t1));
! 182:
! 183: return t0;
! 184: }
! 185:
! 186: target_ulong do_macchiu (target_ulong t0, target_ulong t1)
! 187: {
! 188: set_HIT0_LO(t0, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)t0 * (uint64_t)(uint32_t)t1));
! 189:
! 190: return t0;
! 191: }
! 192:
! 193: target_ulong do_msac (target_ulong t0, target_ulong t1)
! 194: {
! 195: set_HI_LOT0(t0, ((int64_t)get_HILO()) - ((int64_t)(int32_t)t0 * (int64_t)(int32_t)t1));
! 196:
! 197: return t0;
! 198: }
! 199:
! 200: target_ulong do_msachi (target_ulong t0, target_ulong t1)
! 201: {
! 202: set_HIT0_LO(t0, ((int64_t)get_HILO()) - ((int64_t)(int32_t)t0 * (int64_t)(int32_t)t1));
! 203:
! 204: return t0;
! 205: }
! 206:
! 207: target_ulong do_msacu (target_ulong t0, target_ulong t1)
! 208: {
! 209: set_HI_LOT0(t0, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)t0 * (uint64_t)(uint32_t)t1));
! 210:
! 211: return t0;
! 212: }
! 213:
! 214: target_ulong do_msachiu (target_ulong t0, target_ulong t1)
! 215: {
! 216: set_HIT0_LO(t0, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)t0 * (uint64_t)(uint32_t)t1));
! 217:
! 218: return t0;
! 219: }
! 220:
! 221: target_ulong do_mulhi (target_ulong t0, target_ulong t1)
! 222: {
! 223: set_HIT0_LO(t0, (int64_t)(int32_t)t0 * (int64_t)(int32_t)t1);
! 224:
! 225: return t0;
! 226: }
! 227:
! 228: target_ulong do_mulhiu (target_ulong t0, target_ulong t1)
! 229: {
! 230: set_HIT0_LO(t0, (uint64_t)(uint32_t)t0 * (uint64_t)(uint32_t)t1);
! 231:
! 232: return t0;
! 233: }
! 234:
! 235: target_ulong do_mulshi (target_ulong t0, target_ulong t1)
! 236: {
! 237: set_HIT0_LO(t0, 0 - ((int64_t)(int32_t)t0 * (int64_t)(int32_t)t1));
! 238:
! 239: return t0;
! 240: }
! 241:
! 242: target_ulong do_mulshiu (target_ulong t0, target_ulong t1)
! 243: {
! 244: set_HIT0_LO(t0, 0 - ((uint64_t)(uint32_t)t0 * (uint64_t)(uint32_t)t1));
! 245:
! 246: return t0;
! 247: }
! 248:
! 249: #ifdef TARGET_MIPS64
! 250: void do_dmult (target_ulong t0, target_ulong t1)
! 251: {
! 252: muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), t0, t1);
! 253: }
! 254:
! 255: void do_dmultu (target_ulong t0, target_ulong t1)
! 256: {
! 257: mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), t0, t1);
! 258: }
! 259: #endif
! 260:
! 261: #ifdef TARGET_WORDS_BIGENDIAN
! 262: #define GET_LMASK(v) ((v) & 3)
! 263: #define GET_OFFSET(addr, offset) (addr + (offset))
! 264: #else
! 265: #define GET_LMASK(v) (((v) & 3) ^ 3)
! 266: #define GET_OFFSET(addr, offset) (addr - (offset))
! 267: #endif
! 268:
! 269: target_ulong do_lwl(target_ulong t0, target_ulong t1, int mem_idx)
! 270: {
! 271: target_ulong tmp;
! 272:
! 273: #ifdef CONFIG_USER_ONLY
! 274: #define ldfun ldub_raw
! 275: #else
! 276: int (*ldfun)(target_ulong);
! 277:
! 278: switch (mem_idx)
! 279: {
! 280: case 0: ldfun = ldub_kernel; break;
! 281: case 1: ldfun = ldub_super; break;
! 282: default:
! 283: case 2: ldfun = ldub_user; break;
! 284: }
! 285: #endif
! 286: tmp = ldfun(t0);
! 287: t1 = (t1 & 0x00FFFFFF) | (tmp << 24);
! 288:
! 289: if (GET_LMASK(t0) <= 2) {
! 290: tmp = ldfun(GET_OFFSET(t0, 1));
! 291: t1 = (t1 & 0xFF00FFFF) | (tmp << 16);
! 292: }
! 293:
! 294: if (GET_LMASK(t0) <= 1) {
! 295: tmp = ldfun(GET_OFFSET(t0, 2));
! 296: t1 = (t1 & 0xFFFF00FF) | (tmp << 8);
! 297: }
! 298:
! 299: if (GET_LMASK(t0) == 0) {
! 300: tmp = ldfun(GET_OFFSET(t0, 3));
! 301: t1 = (t1 & 0xFFFFFF00) | tmp;
! 302: }
! 303: return (int32_t)t1;
! 304: }
! 305:
! 306: target_ulong do_lwr(target_ulong t0, target_ulong t1, int mem_idx)
! 307: {
! 308: target_ulong tmp;
! 309:
! 310: #ifdef CONFIG_USER_ONLY
! 311: #define ldfun ldub_raw
! 312: #else
! 313: int (*ldfun)(target_ulong);
! 314:
! 315: switch (mem_idx)
! 316: {
! 317: case 0: ldfun = ldub_kernel; break;
! 318: case 1: ldfun = ldub_super; break;
! 319: default:
! 320: case 2: ldfun = ldub_user; break;
! 321: }
! 322: #endif
! 323: tmp = ldfun(t0);
! 324: t1 = (t1 & 0xFFFFFF00) | tmp;
! 325:
! 326: if (GET_LMASK(t0) >= 1) {
! 327: tmp = ldfun(GET_OFFSET(t0, -1));
! 328: t1 = (t1 & 0xFFFF00FF) | (tmp << 8);
! 329: }
! 330:
! 331: if (GET_LMASK(t0) >= 2) {
! 332: tmp = ldfun(GET_OFFSET(t0, -2));
! 333: t1 = (t1 & 0xFF00FFFF) | (tmp << 16);
! 334: }
! 335:
! 336: if (GET_LMASK(t0) == 3) {
! 337: tmp = ldfun(GET_OFFSET(t0, -3));
! 338: t1 = (t1 & 0x00FFFFFF) | (tmp << 24);
! 339: }
! 340: return (int32_t)t1;
! 341: }
! 342:
! 343: void do_swl(target_ulong t0, target_ulong t1, int mem_idx)
! 344: {
! 345: #ifdef CONFIG_USER_ONLY
! 346: #define stfun stb_raw
! 347: #else
! 348: void (*stfun)(target_ulong, int);
! 349:
! 350: switch (mem_idx)
! 351: {
! 352: case 0: stfun = stb_kernel; break;
! 353: case 1: stfun = stb_super; break;
! 354: default:
! 355: case 2: stfun = stb_user; break;
! 356: }
! 357: #endif
! 358: stfun(t0, (uint8_t)(t1 >> 24));
! 359:
! 360: if (GET_LMASK(t0) <= 2)
! 361: stfun(GET_OFFSET(t0, 1), (uint8_t)(t1 >> 16));
! 362:
! 363: if (GET_LMASK(t0) <= 1)
! 364: stfun(GET_OFFSET(t0, 2), (uint8_t)(t1 >> 8));
! 365:
! 366: if (GET_LMASK(t0) == 0)
! 367: stfun(GET_OFFSET(t0, 3), (uint8_t)t1);
! 368: }
! 369:
! 370: void do_swr(target_ulong t0, target_ulong t1, int mem_idx)
! 371: {
! 372: #ifdef CONFIG_USER_ONLY
! 373: #define stfun stb_raw
! 374: #else
! 375: void (*stfun)(target_ulong, int);
! 376:
! 377: switch (mem_idx)
! 378: {
! 379: case 0: stfun = stb_kernel; break;
! 380: case 1: stfun = stb_super; break;
! 381: default:
! 382: case 2: stfun = stb_user; break;
! 383: }
! 384: #endif
! 385: stfun(t0, (uint8_t)t1);
! 386:
! 387: if (GET_LMASK(t0) >= 1)
! 388: stfun(GET_OFFSET(t0, -1), (uint8_t)(t1 >> 8));
! 389:
! 390: if (GET_LMASK(t0) >= 2)
! 391: stfun(GET_OFFSET(t0, -2), (uint8_t)(t1 >> 16));
! 392:
! 393: if (GET_LMASK(t0) == 3)
! 394: stfun(GET_OFFSET(t0, -3), (uint8_t)(t1 >> 24));
! 395: }
! 396:
! 397: #if defined(TARGET_MIPS64)
! 398: /* "half" load and stores. We must do the memory access inline,
! 399: or fault handling won't work. */
! 400:
! 401: #ifdef TARGET_WORDS_BIGENDIAN
! 402: #define GET_LMASK64(v) ((v) & 7)
! 403: #else
! 404: #define GET_LMASK64(v) (((v) & 7) ^ 7)
! 405: #endif
! 406:
! 407: target_ulong do_ldl(target_ulong t0, target_ulong t1, int mem_idx)
! 408: {
! 409: uint64_t tmp;
! 410:
! 411: #ifdef CONFIG_USER_ONLY
! 412: #define ldfun ldub_raw
! 413: #else
! 414: int (*ldfun)(target_ulong);
! 415:
! 416: switch (mem_idx)
! 417: {
! 418: case 0: ldfun = ldub_kernel; break;
! 419: case 1: ldfun = ldub_super; break;
! 420: default:
! 421: case 2: ldfun = ldub_user; break;
! 422: }
! 423: #endif
! 424: tmp = ldfun(t0);
! 425: t1 = (t1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
! 426:
! 427: if (GET_LMASK64(t0) <= 6) {
! 428: tmp = ldfun(GET_OFFSET(t0, 1));
! 429: t1 = (t1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
! 430: }
! 431:
! 432: if (GET_LMASK64(t0) <= 5) {
! 433: tmp = ldfun(GET_OFFSET(t0, 2));
! 434: t1 = (t1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
! 435: }
! 436:
! 437: if (GET_LMASK64(t0) <= 4) {
! 438: tmp = ldfun(GET_OFFSET(t0, 3));
! 439: t1 = (t1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
! 440: }
! 441:
! 442: if (GET_LMASK64(t0) <= 3) {
! 443: tmp = ldfun(GET_OFFSET(t0, 4));
! 444: t1 = (t1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
! 445: }
! 446:
! 447: if (GET_LMASK64(t0) <= 2) {
! 448: tmp = ldfun(GET_OFFSET(t0, 5));
! 449: t1 = (t1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
! 450: }
! 451:
! 452: if (GET_LMASK64(t0) <= 1) {
! 453: tmp = ldfun(GET_OFFSET(t0, 6));
! 454: t1 = (t1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
! 455: }
! 456:
! 457: if (GET_LMASK64(t0) == 0) {
! 458: tmp = ldfun(GET_OFFSET(t0, 7));
! 459: t1 = (t1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
! 460: }
! 461:
! 462: return t1;
! 463: }
! 464:
! 465: target_ulong do_ldr(target_ulong t0, target_ulong t1, int mem_idx)
! 466: {
! 467: uint64_t tmp;
! 468:
! 469: #ifdef CONFIG_USER_ONLY
! 470: #define ldfun ldub_raw
! 471: #else
! 472: int (*ldfun)(target_ulong);
! 473:
! 474: switch (mem_idx)
! 475: {
! 476: case 0: ldfun = ldub_kernel; break;
! 477: case 1: ldfun = ldub_super; break;
! 478: default:
! 479: case 2: ldfun = ldub_user; break;
! 480: }
! 481: #endif
! 482: tmp = ldfun(t0);
! 483: t1 = (t1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
! 484:
! 485: if (GET_LMASK64(t0) >= 1) {
! 486: tmp = ldfun(GET_OFFSET(t0, -1));
! 487: t1 = (t1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
! 488: }
! 489:
! 490: if (GET_LMASK64(t0) >= 2) {
! 491: tmp = ldfun(GET_OFFSET(t0, -2));
! 492: t1 = (t1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
! 493: }
! 494:
! 495: if (GET_LMASK64(t0) >= 3) {
! 496: tmp = ldfun(GET_OFFSET(t0, -3));
! 497: t1 = (t1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
! 498: }
! 499:
! 500: if (GET_LMASK64(t0) >= 4) {
! 501: tmp = ldfun(GET_OFFSET(t0, -4));
! 502: t1 = (t1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
! 503: }
! 504:
! 505: if (GET_LMASK64(t0) >= 5) {
! 506: tmp = ldfun(GET_OFFSET(t0, -5));
! 507: t1 = (t1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
! 508: }
! 509:
! 510: if (GET_LMASK64(t0) >= 6) {
! 511: tmp = ldfun(GET_OFFSET(t0, -6));
! 512: t1 = (t1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
! 513: }
! 514:
! 515: if (GET_LMASK64(t0) == 7) {
! 516: tmp = ldfun(GET_OFFSET(t0, -7));
! 517: t1 = (t1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
! 518: }
! 519:
! 520: return t1;
! 521: }
! 522:
! 523: void do_sdl(target_ulong t0, target_ulong t1, int mem_idx)
! 524: {
! 525: #ifdef CONFIG_USER_ONLY
! 526: #define stfun stb_raw
! 527: #else
! 528: void (*stfun)(target_ulong, int);
! 529:
! 530: switch (mem_idx)
! 531: {
! 532: case 0: stfun = stb_kernel; break;
! 533: case 1: stfun = stb_super; break;
! 534: default:
! 535: case 2: stfun = stb_user; break;
! 536: }
! 537: #endif
! 538: stfun(t0, (uint8_t)(t1 >> 56));
! 539:
! 540: if (GET_LMASK64(t0) <= 6)
! 541: stfun(GET_OFFSET(t0, 1), (uint8_t)(t1 >> 48));
! 542:
! 543: if (GET_LMASK64(t0) <= 5)
! 544: stfun(GET_OFFSET(t0, 2), (uint8_t)(t1 >> 40));
! 545:
! 546: if (GET_LMASK64(t0) <= 4)
! 547: stfun(GET_OFFSET(t0, 3), (uint8_t)(t1 >> 32));
! 548:
! 549: if (GET_LMASK64(t0) <= 3)
! 550: stfun(GET_OFFSET(t0, 4), (uint8_t)(t1 >> 24));
! 551:
! 552: if (GET_LMASK64(t0) <= 2)
! 553: stfun(GET_OFFSET(t0, 5), (uint8_t)(t1 >> 16));
! 554:
! 555: if (GET_LMASK64(t0) <= 1)
! 556: stfun(GET_OFFSET(t0, 6), (uint8_t)(t1 >> 8));
! 557:
! 558: if (GET_LMASK64(t0) <= 0)
! 559: stfun(GET_OFFSET(t0, 7), (uint8_t)t1);
! 560: }
! 561:
! 562: void do_sdr(target_ulong t0, target_ulong t1, int mem_idx)
! 563: {
! 564: #ifdef CONFIG_USER_ONLY
! 565: #define stfun stb_raw
! 566: #else
! 567: void (*stfun)(target_ulong, int);
! 568:
! 569: switch (mem_idx)
! 570: {
! 571: case 0: stfun = stb_kernel; break;
! 572: case 1: stfun = stb_super; break;
! 573: default:
! 574: case 2: stfun = stb_user; break;
! 575: }
! 576: #endif
! 577: stfun(t0, (uint8_t)t1);
! 578:
! 579: if (GET_LMASK64(t0) >= 1)
! 580: stfun(GET_OFFSET(t0, -1), (uint8_t)(t1 >> 8));
! 581:
! 582: if (GET_LMASK64(t0) >= 2)
! 583: stfun(GET_OFFSET(t0, -2), (uint8_t)(t1 >> 16));
! 584:
! 585: if (GET_LMASK64(t0) >= 3)
! 586: stfun(GET_OFFSET(t0, -3), (uint8_t)(t1 >> 24));
! 587:
! 588: if (GET_LMASK64(t0) >= 4)
! 589: stfun(GET_OFFSET(t0, -4), (uint8_t)(t1 >> 32));
! 590:
! 591: if (GET_LMASK64(t0) >= 5)
! 592: stfun(GET_OFFSET(t0, -5), (uint8_t)(t1 >> 40));
! 593:
! 594: if (GET_LMASK64(t0) >= 6)
! 595: stfun(GET_OFFSET(t0, -6), (uint8_t)(t1 >> 48));
! 596:
! 597: if (GET_LMASK64(t0) == 7)
! 598: stfun(GET_OFFSET(t0, -7), (uint8_t)(t1 >> 56));
! 599: }
! 600: #endif /* TARGET_MIPS64 */
! 601:
! 602: #ifndef CONFIG_USER_ONLY
! 603: /* CP0 helpers */
! 604: target_ulong do_mfc0_mvpcontrol (void)
! 605: {
! 606: return env->mvp->CP0_MVPControl;
! 607: }
! 608:
! 609: target_ulong do_mfc0_mvpconf0 (void)
! 610: {
! 611: return env->mvp->CP0_MVPConf0;
! 612: }
! 613:
! 614: target_ulong do_mfc0_mvpconf1 (void)
! 615: {
! 616: return env->mvp->CP0_MVPConf1;
! 617: }
! 618:
! 619: target_ulong do_mfc0_random (void)
! 620: {
! 621: return (int32_t)cpu_mips_get_random(env);
! 622: }
! 623:
! 624: target_ulong do_mfc0_tcstatus (void)
! 625: {
! 626: return env->active_tc.CP0_TCStatus;
! 627: }
! 628:
! 629: target_ulong do_mftc0_tcstatus(void)
! 630: {
! 631: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 632:
! 633: if (other_tc == env->current_tc)
! 634: return env->active_tc.CP0_TCStatus;
! 635: else
! 636: return env->tcs[other_tc].CP0_TCStatus;
! 637: }
! 638:
! 639: target_ulong do_mfc0_tcbind (void)
! 640: {
! 641: return env->active_tc.CP0_TCBind;
! 642: }
! 643:
! 644: target_ulong do_mftc0_tcbind(void)
! 645: {
! 646: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 647:
! 648: if (other_tc == env->current_tc)
! 649: return env->active_tc.CP0_TCBind;
! 650: else
! 651: return env->tcs[other_tc].CP0_TCBind;
! 652: }
! 653:
! 654: target_ulong do_mfc0_tcrestart (void)
! 655: {
! 656: return env->active_tc.PC;
! 657: }
! 658:
! 659: target_ulong do_mftc0_tcrestart(void)
! 660: {
! 661: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 662:
! 663: if (other_tc == env->current_tc)
! 664: return env->active_tc.PC;
! 665: else
! 666: return env->tcs[other_tc].PC;
! 667: }
! 668:
! 669: target_ulong do_mfc0_tchalt (void)
! 670: {
! 671: return env->active_tc.CP0_TCHalt;
! 672: }
! 673:
! 674: target_ulong do_mftc0_tchalt(void)
! 675: {
! 676: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 677:
! 678: if (other_tc == env->current_tc)
! 679: return env->active_tc.CP0_TCHalt;
! 680: else
! 681: return env->tcs[other_tc].CP0_TCHalt;
! 682: }
! 683:
! 684: target_ulong do_mfc0_tccontext (void)
! 685: {
! 686: return env->active_tc.CP0_TCContext;
! 687: }
! 688:
! 689: target_ulong do_mftc0_tccontext(void)
1.1.1.5 root 690: {
1.1.1.7 ! root 691: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 692:
! 693: if (other_tc == env->current_tc)
! 694: return env->active_tc.CP0_TCContext;
! 695: else
! 696: return env->tcs[other_tc].CP0_TCContext;
1.1.1.5 root 697: }
698:
1.1.1.7 ! root 699: target_ulong do_mfc0_tcschedule (void)
1.1.1.5 root 700: {
1.1.1.7 ! root 701: return env->active_tc.CP0_TCSchedule;
1.1.1.5 root 702: }
703:
1.1.1.7 ! root 704: target_ulong do_mftc0_tcschedule(void)
1.1.1.5 root 705: {
1.1.1.7 ! root 706: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 707:
! 708: if (other_tc == env->current_tc)
! 709: return env->active_tc.CP0_TCSchedule;
! 710: else
! 711: return env->tcs[other_tc].CP0_TCSchedule;
1.1.1.5 root 712: }
713:
1.1.1.7 ! root 714: target_ulong do_mfc0_tcschefback (void)
1.1.1.5 root 715: {
1.1.1.7 ! root 716: return env->active_tc.CP0_TCScheFBack;
1.1.1.5 root 717: }
718:
1.1.1.7 ! root 719: target_ulong do_mftc0_tcschefback(void)
1.1.1.5 root 720: {
1.1.1.7 ! root 721: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 722:
! 723: if (other_tc == env->current_tc)
! 724: return env->active_tc.CP0_TCScheFBack;
! 725: else
! 726: return env->tcs[other_tc].CP0_TCScheFBack;
! 727: }
! 728:
! 729: target_ulong do_mfc0_count (void)
! 730: {
! 731: return (int32_t)cpu_mips_get_count(env);
! 732: }
! 733:
! 734: target_ulong do_mftc0_entryhi(void)
! 735: {
! 736: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 737: int32_t tcstatus;
! 738:
! 739: if (other_tc == env->current_tc)
! 740: tcstatus = env->active_tc.CP0_TCStatus;
! 741: else
! 742: tcstatus = env->tcs[other_tc].CP0_TCStatus;
! 743:
! 744: return (env->CP0_EntryHi & ~0xff) | (tcstatus & 0xff);
! 745: }
! 746:
! 747: target_ulong do_mftc0_status(void)
! 748: {
! 749: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 750: target_ulong t0;
! 751: int32_t tcstatus;
! 752:
! 753: if (other_tc == env->current_tc)
! 754: tcstatus = env->active_tc.CP0_TCStatus;
! 755: else
! 756: tcstatus = env->tcs[other_tc].CP0_TCStatus;
! 757:
! 758: t0 = env->CP0_Status & ~0xf1000018;
! 759: t0 |= tcstatus & (0xf << CP0TCSt_TCU0);
! 760: t0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
! 761: t0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
! 762:
! 763: return t0;
! 764: }
! 765:
! 766: target_ulong do_mfc0_lladdr (void)
! 767: {
! 768: return (int32_t)env->CP0_LLAddr >> 4;
! 769: }
! 770:
! 771: target_ulong do_mfc0_watchlo (uint32_t sel)
! 772: {
! 773: return (int32_t)env->CP0_WatchLo[sel];
! 774: }
! 775:
! 776: target_ulong do_mfc0_watchhi (uint32_t sel)
! 777: {
! 778: return env->CP0_WatchHi[sel];
! 779: }
! 780:
! 781: target_ulong do_mfc0_debug (void)
! 782: {
! 783: target_ulong t0 = env->CP0_Debug;
! 784: if (env->hflags & MIPS_HFLAG_DM)
! 785: t0 |= 1 << CP0DB_DM;
! 786:
! 787: return t0;
! 788: }
! 789:
! 790: target_ulong do_mftc0_debug(void)
! 791: {
! 792: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 793: int32_t tcstatus;
! 794:
! 795: if (other_tc == env->current_tc)
! 796: tcstatus = env->active_tc.CP0_Debug_tcstatus;
! 797: else
! 798: tcstatus = env->tcs[other_tc].CP0_Debug_tcstatus;
! 799:
! 800: /* XXX: Might be wrong, check with EJTAG spec. */
! 801: return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
! 802: (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
! 803: }
! 804:
! 805: #if defined(TARGET_MIPS64)
! 806: target_ulong do_dmfc0_tcrestart (void)
! 807: {
! 808: return env->active_tc.PC;
! 809: }
! 810:
! 811: target_ulong do_dmfc0_tchalt (void)
! 812: {
! 813: return env->active_tc.CP0_TCHalt;
! 814: }
! 815:
! 816: target_ulong do_dmfc0_tccontext (void)
! 817: {
! 818: return env->active_tc.CP0_TCContext;
! 819: }
! 820:
! 821: target_ulong do_dmfc0_tcschedule (void)
! 822: {
! 823: return env->active_tc.CP0_TCSchedule;
! 824: }
! 825:
! 826: target_ulong do_dmfc0_tcschefback (void)
! 827: {
! 828: return env->active_tc.CP0_TCScheFBack;
! 829: }
! 830:
! 831: target_ulong do_dmfc0_lladdr (void)
! 832: {
! 833: return env->CP0_LLAddr >> 4;
! 834: }
! 835:
! 836: target_ulong do_dmfc0_watchlo (uint32_t sel)
! 837: {
! 838: return env->CP0_WatchLo[sel];
! 839: }
! 840: #endif /* TARGET_MIPS64 */
! 841:
! 842: void do_mtc0_index (target_ulong t0)
! 843: {
! 844: int num = 1;
! 845: unsigned int tmp = env->tlb->nb_tlb;
! 846:
! 847: do {
! 848: tmp >>= 1;
! 849: num <<= 1;
! 850: } while (tmp);
! 851: env->CP0_Index = (env->CP0_Index & 0x80000000) | (t0 & (num - 1));
! 852: }
! 853:
! 854: void do_mtc0_mvpcontrol (target_ulong t0)
! 855: {
! 856: uint32_t mask = 0;
! 857: uint32_t newval;
! 858:
! 859: if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
! 860: mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
! 861: (1 << CP0MVPCo_EVP);
! 862: if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
! 863: mask |= (1 << CP0MVPCo_STLB);
! 864: newval = (env->mvp->CP0_MVPControl & ~mask) | (t0 & mask);
! 865:
! 866: // TODO: Enable/disable shared TLB, enable/disable VPEs.
! 867:
! 868: env->mvp->CP0_MVPControl = newval;
! 869: }
! 870:
! 871: void do_mtc0_vpecontrol (target_ulong t0)
! 872: {
! 873: uint32_t mask;
! 874: uint32_t newval;
! 875:
! 876: mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
! 877: (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
! 878: newval = (env->CP0_VPEControl & ~mask) | (t0 & mask);
! 879:
! 880: /* Yield scheduler intercept not implemented. */
! 881: /* Gating storage scheduler intercept not implemented. */
! 882:
! 883: // TODO: Enable/disable TCs.
! 884:
! 885: env->CP0_VPEControl = newval;
! 886: }
! 887:
! 888: void do_mtc0_vpeconf0 (target_ulong t0)
! 889: {
! 890: uint32_t mask = 0;
! 891: uint32_t newval;
! 892:
! 893: if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
! 894: if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
! 895: mask |= (0xff << CP0VPEC0_XTC);
! 896: mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
! 897: }
! 898: newval = (env->CP0_VPEConf0 & ~mask) | (t0 & mask);
! 899:
! 900: // TODO: TC exclusive handling due to ERL/EXL.
! 901:
! 902: env->CP0_VPEConf0 = newval;
! 903: }
! 904:
! 905: void do_mtc0_vpeconf1 (target_ulong t0)
! 906: {
! 907: uint32_t mask = 0;
! 908: uint32_t newval;
! 909:
! 910: if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
! 911: mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
! 912: (0xff << CP0VPEC1_NCP1);
! 913: newval = (env->CP0_VPEConf1 & ~mask) | (t0 & mask);
! 914:
! 915: /* UDI not implemented. */
! 916: /* CP2 not implemented. */
! 917:
! 918: // TODO: Handle FPU (CP1) binding.
! 919:
! 920: env->CP0_VPEConf1 = newval;
! 921: }
! 922:
! 923: void do_mtc0_yqmask (target_ulong t0)
! 924: {
! 925: /* Yield qualifier inputs not implemented. */
! 926: env->CP0_YQMask = 0x00000000;
! 927: }
! 928:
! 929: void do_mtc0_vpeopt (target_ulong t0)
! 930: {
! 931: env->CP0_VPEOpt = t0 & 0x0000ffff;
! 932: }
! 933:
! 934: void do_mtc0_entrylo0 (target_ulong t0)
! 935: {
! 936: /* Large physaddr (PABITS) not implemented */
! 937: /* 1k pages not implemented */
! 938: env->CP0_EntryLo0 = t0 & 0x3FFFFFFF;
! 939: }
! 940:
! 941: void do_mtc0_tcstatus (target_ulong t0)
! 942: {
! 943: uint32_t mask = env->CP0_TCStatus_rw_bitmask;
! 944: uint32_t newval;
! 945:
! 946: newval = (env->active_tc.CP0_TCStatus & ~mask) | (t0 & mask);
! 947:
! 948: // TODO: Sync with CP0_Status.
! 949:
! 950: env->active_tc.CP0_TCStatus = newval;
! 951: }
! 952:
! 953: void do_mttc0_tcstatus (target_ulong t0)
! 954: {
! 955: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 956:
! 957: // TODO: Sync with CP0_Status.
! 958:
! 959: if (other_tc == env->current_tc)
! 960: env->active_tc.CP0_TCStatus = t0;
! 961: else
! 962: env->tcs[other_tc].CP0_TCStatus = t0;
! 963: }
! 964:
! 965: void do_mtc0_tcbind (target_ulong t0)
! 966: {
! 967: uint32_t mask = (1 << CP0TCBd_TBE);
! 968: uint32_t newval;
! 969:
! 970: if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
! 971: mask |= (1 << CP0TCBd_CurVPE);
! 972: newval = (env->active_tc.CP0_TCBind & ~mask) | (t0 & mask);
! 973: env->active_tc.CP0_TCBind = newval;
! 974: }
! 975:
! 976: void do_mttc0_tcbind (target_ulong t0)
! 977: {
! 978: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 979: uint32_t mask = (1 << CP0TCBd_TBE);
! 980: uint32_t newval;
! 981:
! 982: if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
! 983: mask |= (1 << CP0TCBd_CurVPE);
! 984: if (other_tc == env->current_tc) {
! 985: newval = (env->active_tc.CP0_TCBind & ~mask) | (t0 & mask);
! 986: env->active_tc.CP0_TCBind = newval;
! 987: } else {
! 988: newval = (env->tcs[other_tc].CP0_TCBind & ~mask) | (t0 & mask);
! 989: env->tcs[other_tc].CP0_TCBind = newval;
! 990: }
! 991: }
! 992:
! 993: void do_mtc0_tcrestart (target_ulong t0)
! 994: {
! 995: env->active_tc.PC = t0;
! 996: env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
! 997: env->CP0_LLAddr = 0ULL;
! 998: /* MIPS16 not implemented. */
! 999: }
! 1000:
! 1001: void do_mttc0_tcrestart (target_ulong t0)
! 1002: {
! 1003: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1004:
! 1005: if (other_tc == env->current_tc) {
! 1006: env->active_tc.PC = t0;
! 1007: env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
! 1008: env->CP0_LLAddr = 0ULL;
! 1009: /* MIPS16 not implemented. */
! 1010: } else {
! 1011: env->tcs[other_tc].PC = t0;
! 1012: env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
! 1013: env->CP0_LLAddr = 0ULL;
! 1014: /* MIPS16 not implemented. */
! 1015: }
! 1016: }
! 1017:
! 1018: void do_mtc0_tchalt (target_ulong t0)
! 1019: {
! 1020: env->active_tc.CP0_TCHalt = t0 & 0x1;
! 1021:
! 1022: // TODO: Halt TC / Restart (if allocated+active) TC.
! 1023: }
! 1024:
! 1025: void do_mttc0_tchalt (target_ulong t0)
! 1026: {
! 1027: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1028:
! 1029: // TODO: Halt TC / Restart (if allocated+active) TC.
! 1030:
! 1031: if (other_tc == env->current_tc)
! 1032: env->active_tc.CP0_TCHalt = t0;
! 1033: else
! 1034: env->tcs[other_tc].CP0_TCHalt = t0;
! 1035: }
! 1036:
! 1037: void do_mtc0_tccontext (target_ulong t0)
! 1038: {
! 1039: env->active_tc.CP0_TCContext = t0;
! 1040: }
! 1041:
! 1042: void do_mttc0_tccontext (target_ulong t0)
! 1043: {
! 1044: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1045:
! 1046: if (other_tc == env->current_tc)
! 1047: env->active_tc.CP0_TCContext = t0;
! 1048: else
! 1049: env->tcs[other_tc].CP0_TCContext = t0;
! 1050: }
! 1051:
! 1052: void do_mtc0_tcschedule (target_ulong t0)
! 1053: {
! 1054: env->active_tc.CP0_TCSchedule = t0;
! 1055: }
! 1056:
! 1057: void do_mttc0_tcschedule (target_ulong t0)
! 1058: {
! 1059: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1060:
! 1061: if (other_tc == env->current_tc)
! 1062: env->active_tc.CP0_TCSchedule = t0;
! 1063: else
! 1064: env->tcs[other_tc].CP0_TCSchedule = t0;
1.1.1.5 root 1065: }
1066:
1.1.1.7 ! root 1067: void do_mtc0_tcschefback (target_ulong t0)
1.1.1.5 root 1068: {
1.1.1.7 ! root 1069: env->active_tc.CP0_TCScheFBack = t0;
1.1.1.5 root 1070: }
1071:
1.1.1.7 ! root 1072: void do_mttc0_tcschefback (target_ulong t0)
1.1.1.5 root 1073: {
1.1.1.7 ! root 1074: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.5 root 1075:
1.1.1.7 ! root 1076: if (other_tc == env->current_tc)
! 1077: env->active_tc.CP0_TCScheFBack = t0;
! 1078: else
! 1079: env->tcs[other_tc].CP0_TCScheFBack = t0;
1.1.1.5 root 1080: }
1081:
1.1.1.7 ! root 1082: void do_mtc0_entrylo1 (target_ulong t0)
1.1.1.5 root 1083: {
1.1.1.7 ! root 1084: /* Large physaddr (PABITS) not implemented */
! 1085: /* 1k pages not implemented */
! 1086: env->CP0_EntryLo1 = t0 & 0x3FFFFFFF;
1.1.1.5 root 1087: }
1088:
1.1.1.7 ! root 1089: void do_mtc0_context (target_ulong t0)
1.1.1.5 root 1090: {
1.1.1.7 ! root 1091: env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (t0 & ~0x007FFFFF);
1.1.1.5 root 1092: }
1093:
1.1.1.7 ! root 1094: void do_mtc0_pagemask (target_ulong t0)
1.1.1.5 root 1095: {
1.1.1.7 ! root 1096: /* 1k pages not implemented */
! 1097: env->CP0_PageMask = t0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1.1.1.5 root 1098: }
1099:
1.1.1.7 ! root 1100: void do_mtc0_pagegrain (target_ulong t0)
1.1.1.5 root 1101: {
1.1.1.7 ! root 1102: /* SmartMIPS not implemented */
! 1103: /* Large physaddr (PABITS) not implemented */
! 1104: /* 1k pages not implemented */
! 1105: env->CP0_PageGrain = 0;
1.1.1.5 root 1106: }
1107:
1.1.1.7 ! root 1108: void do_mtc0_wired (target_ulong t0)
1.1.1.5 root 1109: {
1.1.1.7 ! root 1110: env->CP0_Wired = t0 % env->tlb->nb_tlb;
1.1.1.6 root 1111: }
1112:
1.1.1.7 ! root 1113: void do_mtc0_srsconf0 (target_ulong t0)
1.1.1.6 root 1114: {
1.1.1.7 ! root 1115: env->CP0_SRSConf0 |= t0 & env->CP0_SRSConf0_rw_bitmask;
1.1.1.6 root 1116: }
1117:
1.1.1.7 ! root 1118: void do_mtc0_srsconf1 (target_ulong t0)
1.1.1.6 root 1119: {
1.1.1.7 ! root 1120: env->CP0_SRSConf1 |= t0 & env->CP0_SRSConf1_rw_bitmask;
1.1.1.5 root 1121: }
1.1.1.6 root 1122:
1.1.1.7 ! root 1123: void do_mtc0_srsconf2 (target_ulong t0)
1.1.1.6 root 1124: {
1.1.1.7 ! root 1125: env->CP0_SRSConf2 |= t0 & env->CP0_SRSConf2_rw_bitmask;
1.1.1.6 root 1126: }
1127:
1.1.1.7 ! root 1128: void do_mtc0_srsconf3 (target_ulong t0)
1.1.1.6 root 1129: {
1.1.1.7 ! root 1130: env->CP0_SRSConf3 |= t0 & env->CP0_SRSConf3_rw_bitmask;
1.1.1.6 root 1131: }
1132:
1.1.1.7 ! root 1133: void do_mtc0_srsconf4 (target_ulong t0)
1.1 root 1134: {
1.1.1.7 ! root 1135: env->CP0_SRSConf4 |= t0 & env->CP0_SRSConf4_rw_bitmask;
1.1 root 1136: }
1137:
1.1.1.7 ! root 1138: void do_mtc0_hwrena (target_ulong t0)
1.1 root 1139: {
1.1.1.7 ! root 1140: env->CP0_HWREna = t0 & 0x0000000F;
1.1 root 1141: }
1142:
1.1.1.7 ! root 1143: void do_mtc0_count (target_ulong t0)
1.1 root 1144: {
1.1.1.7 ! root 1145: cpu_mips_store_count(env, t0);
1.1 root 1146: }
1147:
1.1.1.7 ! root 1148: void do_mtc0_entryhi (target_ulong t0)
1.1 root 1149: {
1.1.1.7 ! root 1150: target_ulong old, val;
! 1151:
! 1152: /* 1k pages not implemented */
! 1153: val = t0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
! 1154: #if defined(TARGET_MIPS64)
! 1155: val &= env->SEGMask;
! 1156: #endif
! 1157: old = env->CP0_EntryHi;
! 1158: env->CP0_EntryHi = val;
! 1159: if (env->CP0_Config3 & (1 << CP0C3_MT)) {
! 1160: uint32_t tcst = env->active_tc.CP0_TCStatus & ~0xff;
! 1161: env->active_tc.CP0_TCStatus = tcst | (val & 0xff);
! 1162: }
! 1163: /* If the ASID changes, flush qemu's TLB. */
! 1164: if ((old & 0xFF) != (val & 0xFF))
! 1165: cpu_mips_tlb_flush(env, 1);
! 1166: }
! 1167:
! 1168: void do_mttc0_entryhi(target_ulong t0)
! 1169: {
! 1170: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1171: int32_t tcstatus;
! 1172:
! 1173: env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (t0 & ~0xff);
! 1174: if (other_tc == env->current_tc) {
! 1175: tcstatus = (env->active_tc.CP0_TCStatus & ~0xff) | (t0 & 0xff);
! 1176: env->active_tc.CP0_TCStatus = tcstatus;
! 1177: } else {
! 1178: tcstatus = (env->tcs[other_tc].CP0_TCStatus & ~0xff) | (t0 & 0xff);
! 1179: env->tcs[other_tc].CP0_TCStatus = tcstatus;
! 1180: }
1.1 root 1181: }
1182:
1.1.1.7 ! root 1183: void do_mtc0_compare (target_ulong t0)
1.1 root 1184: {
1.1.1.7 ! root 1185: cpu_mips_store_compare(env, t0);
1.1 root 1186: }
1187:
1.1.1.7 ! root 1188: void do_mtc0_status (target_ulong t0)
1.1 root 1189: {
1.1.1.7 ! root 1190: uint32_t val, old;
! 1191: uint32_t mask = env->CP0_Status_rw_bitmask;
1.1 root 1192:
1.1.1.7 ! root 1193: val = t0 & mask;
! 1194: old = env->CP0_Status;
! 1195: env->CP0_Status = (env->CP0_Status & ~mask) | val;
! 1196: compute_hflags(env);
! 1197: if (qemu_loglevel_mask(CPU_LOG_EXEC))
! 1198: do_mtc0_status_debug(old, val);
! 1199: cpu_mips_update_irq(env);
1.1 root 1200: }
1201:
1.1.1.7 ! root 1202: void do_mttc0_status(target_ulong t0)
1.1 root 1203: {
1.1.1.7 ! root 1204: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1205: int32_t tcstatus = env->tcs[other_tc].CP0_TCStatus;
1.1 root 1206:
1.1.1.7 ! root 1207: env->CP0_Status = t0 & ~0xf1000018;
! 1208: tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (t0 & (0xf << CP0St_CU0));
! 1209: tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((t0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
! 1210: tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((t0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
! 1211: if (other_tc == env->current_tc)
! 1212: env->active_tc.CP0_TCStatus = tcstatus;
! 1213: else
! 1214: env->tcs[other_tc].CP0_TCStatus = tcstatus;
1.1 root 1215: }
1216:
1.1.1.7 ! root 1217: void do_mtc0_intctl (target_ulong t0)
1.1 root 1218: {
1.1.1.7 ! root 1219: /* vectored interrupts not implemented, no performance counters. */
! 1220: env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (t0 & 0x000002e0);
1.1 root 1221: }
1222:
1.1.1.7 ! root 1223: void do_mtc0_srsctl (target_ulong t0)
1.1.1.6 root 1224: {
1.1.1.7 ! root 1225: uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
! 1226: env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (t0 & mask);
1.1.1.6 root 1227: }
1228:
1.1.1.7 ! root 1229: void do_mtc0_cause (target_ulong t0)
1.1.1.6 root 1230: {
1.1.1.7 ! root 1231: uint32_t mask = 0x00C00300;
! 1232: uint32_t old = env->CP0_Cause;
! 1233:
! 1234: if (env->insn_flags & ISA_MIPS32R2)
! 1235: mask |= 1 << CP0Ca_DC;
! 1236:
! 1237: env->CP0_Cause = (env->CP0_Cause & ~mask) | (t0 & mask);
! 1238:
! 1239: if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
! 1240: if (env->CP0_Cause & (1 << CP0Ca_DC))
! 1241: cpu_mips_stop_count(env);
! 1242: else
! 1243: cpu_mips_start_count(env);
! 1244: }
! 1245:
! 1246: /* Handle the software interrupt as an hardware one, as they
! 1247: are very similar */
! 1248: if (t0 & CP0Ca_IP_mask) {
! 1249: cpu_mips_update_irq(env);
! 1250: }
1.1.1.6 root 1251: }
1252:
1.1.1.7 ! root 1253: void do_mtc0_ebase (target_ulong t0)
1.1.1.6 root 1254: {
1.1.1.7 ! root 1255: /* vectored interrupts not implemented */
! 1256: /* Multi-CPU not implemented */
! 1257: env->CP0_EBase = 0x80000000 | (t0 & 0x3FFFF000);
1.1.1.6 root 1258: }
1259:
1.1.1.7 ! root 1260: void do_mtc0_config0 (target_ulong t0)
1.1.1.6 root 1261: {
1.1.1.7 ! root 1262: env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (t0 & 0x00000007);
1.1.1.6 root 1263: }
1264:
1.1.1.7 ! root 1265: void do_mtc0_config2 (target_ulong t0)
1.1.1.6 root 1266: {
1.1.1.7 ! root 1267: /* tertiary/secondary caches not implemented */
! 1268: env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1.1.1.6 root 1269: }
1270:
1.1.1.7 ! root 1271: void do_mtc0_watchlo (target_ulong t0, uint32_t sel)
1.1.1.6 root 1272: {
1.1.1.7 ! root 1273: /* Watch exceptions for instructions, data loads, data stores
! 1274: not implemented. */
! 1275: env->CP0_WatchLo[sel] = (t0 & ~0x7);
1.1.1.6 root 1276: }
1277:
1.1.1.7 ! root 1278: void do_mtc0_watchhi (target_ulong t0, uint32_t sel)
1.1.1.6 root 1279: {
1.1.1.7 ! root 1280: env->CP0_WatchHi[sel] = (t0 & 0x40FF0FF8);
! 1281: env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & t0 & 0x7);
1.1.1.6 root 1282: }
1283:
1.1.1.7 ! root 1284: void do_mtc0_xcontext (target_ulong t0)
1.1.1.6 root 1285: {
1.1.1.7 ! root 1286: target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
! 1287: env->CP0_XContext = (env->CP0_XContext & mask) | (t0 & ~mask);
1.1.1.6 root 1288: }
1289:
1.1.1.7 ! root 1290: void do_mtc0_framemask (target_ulong t0)
1.1.1.6 root 1291: {
1.1.1.7 ! root 1292: env->CP0_Framemask = t0; /* XXX */
1.1.1.6 root 1293: }
1294:
1.1.1.7 ! root 1295: void do_mtc0_debug (target_ulong t0)
1.1.1.6 root 1296: {
1.1.1.7 ! root 1297: env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (t0 & 0x13300120);
! 1298: if (t0 & (1 << CP0DB_DM))
! 1299: env->hflags |= MIPS_HFLAG_DM;
! 1300: else
! 1301: env->hflags &= ~MIPS_HFLAG_DM;
1.1.1.6 root 1302: }
1303:
1.1.1.7 ! root 1304: void do_mttc0_debug(target_ulong t0)
1.1.1.6 root 1305: {
1.1.1.7 ! root 1306: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1307: uint32_t val = t0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
! 1308:
! 1309: /* XXX: Might be wrong, check with EJTAG spec. */
! 1310: if (other_tc == env->current_tc)
! 1311: env->active_tc.CP0_Debug_tcstatus = val;
! 1312: else
! 1313: env->tcs[other_tc].CP0_Debug_tcstatus = val;
! 1314: env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
! 1315: (t0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1.1.1.6 root 1316: }
1317:
1.1.1.7 ! root 1318: void do_mtc0_performance0 (target_ulong t0)
1.1.1.6 root 1319: {
1.1.1.7 ! root 1320: env->CP0_Performance0 = t0 & 0x000007ff;
1.1.1.6 root 1321: }
1322:
1.1.1.7 ! root 1323: void do_mtc0_taglo (target_ulong t0)
1.1.1.6 root 1324: {
1.1.1.7 ! root 1325: env->CP0_TagLo = t0 & 0xFFFFFCF6;
1.1.1.6 root 1326: }
1327:
1.1.1.7 ! root 1328: void do_mtc0_datalo (target_ulong t0)
1.1.1.5 root 1329: {
1.1.1.7 ! root 1330: env->CP0_DataLo = t0; /* XXX */
1.1.1.5 root 1331: }
1332:
1.1.1.7 ! root 1333: void do_mtc0_taghi (target_ulong t0)
1.1.1.5 root 1334: {
1.1.1.7 ! root 1335: env->CP0_TagHi = t0; /* XXX */
1.1.1.5 root 1336: }
1337:
1.1.1.7 ! root 1338: void do_mtc0_datahi (target_ulong t0)
1.1.1.5 root 1339: {
1.1.1.7 ! root 1340: env->CP0_DataHi = t0; /* XXX */
1.1.1.5 root 1341: }
1342:
1.1.1.7 ! root 1343: void do_mtc0_status_debug(uint32_t old, uint32_t val)
1.1.1.5 root 1344: {
1.1.1.7 ! root 1345: qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
! 1346: old, old & env->CP0_Cause & CP0Ca_IP_mask,
! 1347: val, val & env->CP0_Cause & CP0Ca_IP_mask,
! 1348: env->CP0_Cause);
! 1349: switch (env->hflags & MIPS_HFLAG_KSU) {
! 1350: case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
! 1351: case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
! 1352: case MIPS_HFLAG_KM: qemu_log("\n"); break;
! 1353: default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1.1.1.5 root 1354: }
1355: }
1356:
1.1.1.7 ! root 1357: void do_mtc0_status_irqraise_debug(void)
1.1.1.5 root 1358: {
1.1.1.7 ! root 1359: qemu_log("Raise pending IRQs\n");
1.1.1.5 root 1360: }
1361:
1.1.1.7 ! root 1362: /* MIPS MT functions */
! 1363: target_ulong do_mftgpr(uint32_t sel)
1.1.1.5 root 1364: {
1.1.1.7 ! root 1365: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1366:
! 1367: if (other_tc == env->current_tc)
! 1368: return env->active_tc.gpr[sel];
! 1369: else
! 1370: return env->tcs[other_tc].gpr[sel];
1.1.1.5 root 1371: }
1372:
1.1.1.7 ! root 1373: target_ulong do_mftlo(uint32_t sel)
1.1.1.5 root 1374: {
1.1.1.7 ! root 1375: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1376:
! 1377: if (other_tc == env->current_tc)
! 1378: return env->active_tc.LO[sel];
! 1379: else
! 1380: return env->tcs[other_tc].LO[sel];
1.1.1.5 root 1381: }
1382:
1.1.1.7 ! root 1383: target_ulong do_mfthi(uint32_t sel)
1.1.1.5 root 1384: {
1.1.1.7 ! root 1385: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1386:
! 1387: if (other_tc == env->current_tc)
! 1388: return env->active_tc.HI[sel];
! 1389: else
! 1390: return env->tcs[other_tc].HI[sel];
1.1.1.5 root 1391: }
1392:
1.1.1.7 ! root 1393: target_ulong do_mftacx(uint32_t sel)
1.1.1.5 root 1394: {
1.1.1.7 ! root 1395: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1396:
! 1397: if (other_tc == env->current_tc)
! 1398: return env->active_tc.ACX[sel];
! 1399: else
! 1400: return env->tcs[other_tc].ACX[sel];
1.1.1.2 root 1401: }
1402:
1.1.1.7 ! root 1403: target_ulong do_mftdsp(void)
1.1.1.2 root 1404: {
1.1.1.7 ! root 1405: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1406:
! 1407: if (other_tc == env->current_tc)
! 1408: return env->active_tc.DSPControl;
! 1409: else
! 1410: return env->tcs[other_tc].DSPControl;
1.1.1.2 root 1411: }
1412:
1.1.1.7 ! root 1413: void do_mttgpr(target_ulong t0, uint32_t sel)
1.1.1.2 root 1414: {
1.1.1.7 ! root 1415: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1416:
! 1417: if (other_tc == env->current_tc)
! 1418: env->active_tc.gpr[sel] = t0;
! 1419: else
! 1420: env->tcs[other_tc].gpr[sel] = t0;
1.1.1.2 root 1421: }
1422:
1.1.1.7 ! root 1423: void do_mttlo(target_ulong t0, uint32_t sel)
1.1.1.2 root 1424: {
1.1.1.7 ! root 1425: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1426:
! 1427: if (other_tc == env->current_tc)
! 1428: env->active_tc.LO[sel] = t0;
! 1429: else
! 1430: env->tcs[other_tc].LO[sel] = t0;
1.1.1.2 root 1431: }
1432:
1.1.1.7 ! root 1433: void do_mtthi(target_ulong t0, uint32_t sel)
1.1.1.2 root 1434: {
1.1.1.7 ! root 1435: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1436:
! 1437: if (other_tc == env->current_tc)
! 1438: env->active_tc.HI[sel] = t0;
! 1439: else
! 1440: env->tcs[other_tc].HI[sel] = t0;
1.1.1.2 root 1441: }
1.1.1.5 root 1442:
1.1.1.7 ! root 1443: void do_mttacx(target_ulong t0, uint32_t sel)
1.1.1.5 root 1444: {
1.1.1.7 ! root 1445: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.5 root 1446:
1.1.1.7 ! root 1447: if (other_tc == env->current_tc)
! 1448: env->active_tc.ACX[sel] = t0;
! 1449: else
! 1450: env->tcs[other_tc].ACX[sel] = t0;
! 1451: }
1.1.1.2 root 1452:
1.1.1.7 ! root 1453: void do_mttdsp(target_ulong t0)
1.1 root 1454: {
1.1.1.7 ! root 1455: int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
! 1456:
! 1457: if (other_tc == env->current_tc)
! 1458: env->active_tc.DSPControl = t0;
! 1459: else
! 1460: env->tcs[other_tc].DSPControl = t0;
1.1.1.5 root 1461: }
1.1 root 1462:
1.1.1.7 ! root 1463: /* MIPS MT functions */
! 1464: target_ulong do_dmt(target_ulong t0)
1.1.1.5 root 1465: {
1.1.1.7 ! root 1466: // TODO
! 1467: t0 = 0;
! 1468: // rt = t0
! 1469:
! 1470: return t0;
1.1 root 1471: }
1472:
1.1.1.7 ! root 1473: target_ulong do_emt(target_ulong t0)
1.1 root 1474: {
1.1.1.7 ! root 1475: // TODO
! 1476: t0 = 0;
! 1477: // rt = t0
! 1478:
! 1479: return t0;
1.1.1.5 root 1480: }
1.1 root 1481:
1.1.1.7 ! root 1482: target_ulong do_dvpe(target_ulong t0)
1.1.1.5 root 1483: {
1.1.1.7 ! root 1484: // TODO
! 1485: t0 = 0;
! 1486: // rt = t0
! 1487:
! 1488: return t0;
1.1 root 1489: }
1490:
1.1.1.7 ! root 1491: target_ulong do_evpe(target_ulong t0)
1.1.1.4 root 1492: {
1.1.1.7 ! root 1493: // TODO
! 1494: t0 = 0;
! 1495: // rt = t0
1.1.1.4 root 1496:
1.1.1.7 ! root 1497: return t0;
! 1498: }
! 1499: #endif /* !CONFIG_USER_ONLY */
1.1.1.4 root 1500:
1.1.1.7 ! root 1501: void do_fork(target_ulong t0, target_ulong t1)
! 1502: {
! 1503: // t0 = rt, t1 = rs
! 1504: t0 = 0;
! 1505: // TODO: store to TC register
! 1506: }
! 1507:
! 1508: target_ulong do_yield(target_ulong t0)
! 1509: {
! 1510: if (t0 < 0) {
! 1511: /* No scheduling policy implemented. */
! 1512: if (t0 != -2) {
! 1513: if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
! 1514: env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
! 1515: env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
! 1516: env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
! 1517: do_raise_exception(EXCP_THREAD);
! 1518: }
! 1519: }
! 1520: } else if (t0 == 0) {
! 1521: if (0 /* TODO: TC underflow */) {
! 1522: env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
! 1523: do_raise_exception(EXCP_THREAD);
! 1524: } else {
! 1525: // TODO: Deallocate TC
! 1526: }
! 1527: } else if (t0 > 0) {
! 1528: /* Yield qualifier inputs not implemented. */
! 1529: env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
! 1530: env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
! 1531: do_raise_exception(EXCP_THREAD);
1.1.1.4 root 1532: }
1.1.1.7 ! root 1533: return env->CP0_YQMask;
1.1.1.4 root 1534: }
1535:
1.1.1.7 ! root 1536: #ifndef CONFIG_USER_ONLY
1.1 root 1537: /* TLB management */
1.1.1.5 root 1538: void cpu_mips_tlb_flush (CPUState *env, int flush_global)
1.1 root 1539: {
1.1.1.5 root 1540: /* Flush qemu's TLB and discard all shadowed entries. */
1541: tlb_flush (env, flush_global);
1.1.1.6 root 1542: env->tlb->tlb_in_use = env->tlb->nb_tlb;
1.1.1.5 root 1543: }
1.1 root 1544:
1.1.1.6 root 1545: static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
1.1.1.5 root 1546: {
1547: /* Discard entries from env->tlb[first] onwards. */
1.1.1.6 root 1548: while (env->tlb->tlb_in_use > first) {
1549: r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
1.1 root 1550: }
1551: }
1552:
1.1.1.6 root 1553: static void r4k_fill_tlb (int idx)
1.1 root 1554: {
1.1.1.6 root 1555: r4k_tlb_t *tlb;
1.1 root 1556:
1557: /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
1.1.1.6 root 1558: tlb = &env->tlb->mmu.r4k.tlb[idx];
1559: tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
1560: #if defined(TARGET_MIPS64)
1561: tlb->VPN &= env->SEGMask;
1562: #endif
1.1.1.3 root 1563: tlb->ASID = env->CP0_EntryHi & 0xFF;
1.1.1.5 root 1564: tlb->PageMask = env->CP0_PageMask;
1.1 root 1565: tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1.1.1.3 root 1566: tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
1567: tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
1568: tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
1.1 root 1569: tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
1.1.1.3 root 1570: tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
1571: tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
1572: tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
1.1 root 1573: tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
1574: }
1575:
1.1.1.6 root 1576: void r4k_do_tlbwi (void)
1.1 root 1577: {
1.1.1.7 ! root 1578: int idx;
! 1579:
! 1580: idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
! 1581:
1.1.1.5 root 1582: /* Discard cached TLB entries. We could avoid doing this if the
1583: tlbwi is just upgrading access permissions on the current entry;
1584: that might be a further win. */
1.1.1.6 root 1585: r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
1.1.1.5 root 1586:
1.1.1.7 ! root 1587: r4k_invalidate_tlb(env, idx, 0);
! 1588: r4k_fill_tlb(idx);
1.1 root 1589: }
1590:
1.1.1.6 root 1591: void r4k_do_tlbwr (void)
1.1 root 1592: {
1593: int r = cpu_mips_get_random(env);
1594:
1.1.1.6 root 1595: r4k_invalidate_tlb(env, r, 1);
1596: r4k_fill_tlb(r);
1.1 root 1597: }
1598:
1.1.1.6 root 1599: void r4k_do_tlbp (void)
1.1 root 1600: {
1.1.1.6 root 1601: r4k_tlb_t *tlb;
1602: target_ulong mask;
1.1 root 1603: target_ulong tag;
1.1.1.6 root 1604: target_ulong VPN;
1.1 root 1605: uint8_t ASID;
1606: int i;
1607:
1.1.1.4 root 1608: ASID = env->CP0_EntryHi & 0xFF;
1.1.1.6 root 1609: for (i = 0; i < env->tlb->nb_tlb; i++) {
1610: tlb = &env->tlb->mmu.r4k.tlb[i];
1611: /* 1k pages are not supported. */
1612: mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1613: tag = env->CP0_EntryHi & ~mask;
1614: VPN = tlb->VPN & ~mask;
1.1 root 1615: /* Check ASID, virtual page number & size */
1.1.1.6 root 1616: if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1.1 root 1617: /* TLB match */
1.1.1.5 root 1618: env->CP0_Index = i;
1.1 root 1619: break;
1620: }
1621: }
1.1.1.6 root 1622: if (i == env->tlb->nb_tlb) {
1.1.1.5 root 1623: /* No match. Discard any shadow entries, if any of them match. */
1.1.1.6 root 1624: for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
1.1.1.7 ! root 1625: tlb = &env->tlb->mmu.r4k.tlb[i];
! 1626: /* 1k pages are not supported. */
! 1627: mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
! 1628: tag = env->CP0_EntryHi & ~mask;
! 1629: VPN = tlb->VPN & ~mask;
! 1630: /* Check ASID, virtual page number & size */
! 1631: if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1.1.1.6 root 1632: r4k_mips_tlb_flush_extra (env, i);
1.1.1.7 ! root 1633: break;
! 1634: }
! 1635: }
1.1.1.5 root 1636:
1637: env->CP0_Index |= 0x80000000;
1.1 root 1638: }
1639: }
1640:
1.1.1.6 root 1641: void r4k_do_tlbr (void)
1.1 root 1642: {
1.1.1.6 root 1643: r4k_tlb_t *tlb;
1.1.1.3 root 1644: uint8_t ASID;
1.1.1.7 ! root 1645: int idx;
1.1 root 1646:
1.1.1.3 root 1647: ASID = env->CP0_EntryHi & 0xFF;
1.1.1.7 ! root 1648: idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
! 1649: tlb = &env->tlb->mmu.r4k.tlb[idx];
1.1.1.2 root 1650:
1651: /* If this will change the current ASID, flush qemu's TLB. */
1.1.1.5 root 1652: if (ASID != tlb->ASID)
1653: cpu_mips_tlb_flush (env, 1);
1654:
1.1.1.6 root 1655: r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1.1.1.2 root 1656:
1.1 root 1657: env->CP0_EntryHi = tlb->VPN | tlb->ASID;
1.1.1.5 root 1658: env->CP0_PageMask = tlb->PageMask;
1659: env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
1660: (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
1661: env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
1662: (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1.1 root 1663: }
1664:
1.1.1.7 ! root 1665: void do_tlbwi(void)
! 1666: {
! 1667: env->tlb->do_tlbwi();
! 1668: }
! 1669:
! 1670: void do_tlbwr(void)
! 1671: {
! 1672: env->tlb->do_tlbwr();
! 1673: }
! 1674:
! 1675: void do_tlbp(void)
! 1676: {
! 1677: env->tlb->do_tlbp();
! 1678: }
! 1679:
! 1680: void do_tlbr(void)
! 1681: {
! 1682: env->tlb->do_tlbr();
! 1683: }
! 1684:
! 1685: /* Specials */
! 1686: target_ulong do_di (void)
! 1687: {
! 1688: target_ulong t0 = env->CP0_Status;
1.1.1.2 root 1689:
1.1.1.7 ! root 1690: env->CP0_Status = t0 & ~(1 << CP0St_IE);
! 1691: cpu_mips_update_irq(env);
! 1692:
! 1693: return t0;
! 1694: }
! 1695:
! 1696: target_ulong do_ei (void)
1.1 root 1697: {
1.1.1.7 ! root 1698: target_ulong t0 = env->CP0_Status;
! 1699:
! 1700: env->CP0_Status = t0 | (1 << CP0St_IE);
! 1701: cpu_mips_update_irq(env);
! 1702:
! 1703: return t0;
1.1 root 1704: }
1705:
1.1.1.7 ! root 1706: static void debug_pre_eret (void)
1.1 root 1707: {
1.1.1.7 ! root 1708: if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
! 1709: qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
! 1710: env->active_tc.PC, env->CP0_EPC);
! 1711: if (env->CP0_Status & (1 << CP0St_ERL))
! 1712: qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
! 1713: if (env->hflags & MIPS_HFLAG_DM)
! 1714: qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
! 1715: qemu_log("\n");
1.1 root 1716: }
1717: }
1718:
1.1.1.7 ! root 1719: static void debug_post_eret (void)
1.1 root 1720: {
1.1.1.7 ! root 1721: if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
! 1722: qemu_log(" => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
! 1723: env->active_tc.PC, env->CP0_EPC);
! 1724: if (env->CP0_Status & (1 << CP0St_ERL))
! 1725: qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
! 1726: if (env->hflags & MIPS_HFLAG_DM)
! 1727: qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
! 1728: switch (env->hflags & MIPS_HFLAG_KSU) {
! 1729: case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
! 1730: case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
! 1731: case MIPS_HFLAG_KM: qemu_log("\n"); break;
! 1732: default: cpu_abort(env, "Invalid MMU mode!\n"); break;
! 1733: }
! 1734: }
1.1.1.6 root 1735: }
1736:
1.1.1.7 ! root 1737: void do_eret (void)
1.1.1.6 root 1738: {
1.1.1.7 ! root 1739: debug_pre_eret();
! 1740: if (env->CP0_Status & (1 << CP0St_ERL)) {
! 1741: env->active_tc.PC = env->CP0_ErrorEPC;
! 1742: env->CP0_Status &= ~(1 << CP0St_ERL);
! 1743: } else {
! 1744: env->active_tc.PC = env->CP0_EPC;
! 1745: env->CP0_Status &= ~(1 << CP0St_EXL);
1.1 root 1746: }
1.1.1.7 ! root 1747: compute_hflags(env);
! 1748: debug_post_eret();
! 1749: env->CP0_LLAddr = 1;
! 1750: }
! 1751:
! 1752: void do_deret (void)
! 1753: {
! 1754: debug_pre_eret();
! 1755: env->active_tc.PC = env->CP0_DEPC;
! 1756: env->hflags &= MIPS_HFLAG_DM;
! 1757: compute_hflags(env);
! 1758: debug_post_eret();
! 1759: env->CP0_LLAddr = 1;
! 1760: }
! 1761: #endif /* !CONFIG_USER_ONLY */
! 1762:
! 1763: target_ulong do_rdhwr_cpunum(void)
! 1764: {
! 1765: if ((env->hflags & MIPS_HFLAG_CP0) ||
! 1766: (env->CP0_HWREna & (1 << 0)))
! 1767: return env->CP0_EBase & 0x3ff;
! 1768: else
! 1769: do_raise_exception(EXCP_RI);
! 1770:
! 1771: return 0;
! 1772: }
! 1773:
! 1774: target_ulong do_rdhwr_synci_step(void)
! 1775: {
! 1776: if ((env->hflags & MIPS_HFLAG_CP0) ||
! 1777: (env->CP0_HWREna & (1 << 1)))
! 1778: return env->SYNCI_Step;
! 1779: else
! 1780: do_raise_exception(EXCP_RI);
! 1781:
! 1782: return 0;
! 1783: }
! 1784:
! 1785: target_ulong do_rdhwr_cc(void)
! 1786: {
! 1787: if ((env->hflags & MIPS_HFLAG_CP0) ||
! 1788: (env->CP0_HWREna & (1 << 2)))
! 1789: return env->CP0_Count;
! 1790: else
! 1791: do_raise_exception(EXCP_RI);
! 1792:
! 1793: return 0;
! 1794: }
! 1795:
! 1796: target_ulong do_rdhwr_ccres(void)
! 1797: {
! 1798: if ((env->hflags & MIPS_HFLAG_CP0) ||
! 1799: (env->CP0_HWREna & (1 << 3)))
! 1800: return env->CCRes;
! 1801: else
! 1802: do_raise_exception(EXCP_RI);
! 1803:
! 1804: return 0;
1.1 root 1805: }
1806:
1807: void do_pmon (int function)
1808: {
1809: function /= 2;
1810: switch (function) {
1811: case 2: /* TODO: char inbyte(int waitflag); */
1.1.1.7 ! root 1812: if (env->active_tc.gpr[4] == 0)
! 1813: env->active_tc.gpr[2] = -1;
1.1 root 1814: /* Fall through */
1815: case 11: /* TODO: char inbyte (void); */
1.1.1.7 ! root 1816: env->active_tc.gpr[2] = -1;
1.1 root 1817: break;
1818: case 3:
1819: case 12:
1.1.1.7 ! root 1820: printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
1.1 root 1821: break;
1822: case 17:
1823: break;
1824: case 158:
1825: {
1.1.1.7 ! root 1826: unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4];
1.1 root 1827: printf("%s", fmt);
1828: }
1829: break;
1830: }
1831: }
1832:
1.1.1.7 ! root 1833: void do_wait (void)
! 1834: {
! 1835: env->halted = 1;
! 1836: do_raise_exception(EXCP_HLT);
! 1837: }
! 1838:
1.1.1.6 root 1839: #if !defined(CONFIG_USER_ONLY)
1.1 root 1840:
1.1.1.2 root 1841: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
1842:
1.1 root 1843: #define MMUSUFFIX _mmu
1.1.1.2 root 1844: #define ALIGNED_ONLY
1.1 root 1845:
1846: #define SHIFT 0
1847: #include "softmmu_template.h"
1848:
1849: #define SHIFT 1
1850: #include "softmmu_template.h"
1851:
1852: #define SHIFT 2
1853: #include "softmmu_template.h"
1854:
1855: #define SHIFT 3
1856: #include "softmmu_template.h"
1857:
1.1.1.2 root 1858: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
1859: {
1860: env->CP0_BadVAddr = addr;
1861: do_restore_state (retaddr);
1862: do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
1863: }
1864:
1.1.1.6 root 1865: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1 root 1866: {
1867: TranslationBlock *tb;
1868: CPUState *saved_env;
1869: unsigned long pc;
1870: int ret;
1871:
1872: /* XXX: hack to restore env in all cases, even if not called from
1873: generated code */
1874: saved_env = env;
1875: env = cpu_single_env;
1.1.1.6 root 1876: ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1 root 1877: if (ret) {
1878: if (retaddr) {
1879: /* now we have a real cpu fault */
1880: pc = (unsigned long)retaddr;
1881: tb = tb_find_pc(pc);
1882: if (tb) {
1883: /* the PC is inside the translated code. It means that we have
1884: a virtual CPU fault */
1885: cpu_restore_state(tb, env, pc, NULL);
1886: }
1887: }
1888: do_raise_exception_err(env->exception_index, env->error_code);
1889: }
1890: env = saved_env;
1891: }
1892:
1.1.1.6 root 1893: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1.1.1.7 ! root 1894: int unused, int size)
1.1.1.6 root 1895: {
1896: if (is_exec)
1897: do_raise_exception(EXCP_IBE);
1898: else
1899: do_raise_exception(EXCP_DBE);
1900: }
1.1.1.7 ! root 1901: #endif /* !CONFIG_USER_ONLY */
1.1.1.6 root 1902:
1903: /* Complex FPU operations which may need stack space. */
1904:
1905: #define FLOAT_ONE32 make_float32(0x3f8 << 20)
1906: #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
1907: #define FLOAT_TWO32 make_float32(1 << 30)
1908: #define FLOAT_TWO64 make_float64(1ULL << 62)
1909: #define FLOAT_QNAN32 0x7fbfffff
1910: #define FLOAT_QNAN64 0x7ff7ffffffffffffULL
1911: #define FLOAT_SNAN32 0x7fffffff
1912: #define FLOAT_SNAN64 0x7fffffffffffffffULL
1913:
1914: /* convert MIPS rounding mode in FCR31 to IEEE library */
1915: unsigned int ieee_rm[] = {
1916: float_round_nearest_even,
1917: float_round_to_zero,
1918: float_round_up,
1919: float_round_down
1920: };
1921:
1922: #define RESTORE_ROUNDING_MODE \
1.1.1.7 ! root 1923: set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
1.1.1.6 root 1924:
1.1.1.7 ! root 1925: target_ulong do_cfc1 (uint32_t reg)
1.1.1.6 root 1926: {
1.1.1.7 ! root 1927: target_ulong t0;
! 1928:
1.1.1.6 root 1929: switch (reg) {
1930: case 0:
1.1.1.7 ! root 1931: t0 = (int32_t)env->active_fpu.fcr0;
1.1.1.6 root 1932: break;
1933: case 25:
1.1.1.7 ! root 1934: t0 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
1.1.1.6 root 1935: break;
1936: case 26:
1.1.1.7 ! root 1937: t0 = env->active_fpu.fcr31 & 0x0003f07c;
1.1.1.6 root 1938: break;
1939: case 28:
1.1.1.7 ! root 1940: t0 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
1.1.1.6 root 1941: break;
1942: default:
1.1.1.7 ! root 1943: t0 = (int32_t)env->active_fpu.fcr31;
1.1.1.6 root 1944: break;
1945: }
1.1.1.7 ! root 1946:
! 1947: return t0;
1.1.1.6 root 1948: }
1949:
1.1.1.7 ! root 1950: void do_ctc1 (target_ulong t0, uint32_t reg)
1.1.1.6 root 1951: {
1952: switch(reg) {
1953: case 25:
1.1.1.7 ! root 1954: if (t0 & 0xffffff00)
1.1.1.6 root 1955: return;
1.1.1.7 ! root 1956: env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((t0 & 0xfe) << 24) |
! 1957: ((t0 & 0x1) << 23);
1.1.1.6 root 1958: break;
1959: case 26:
1.1.1.7 ! root 1960: if (t0 & 0x007c0000)
1.1.1.6 root 1961: return;
1.1.1.7 ! root 1962: env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (t0 & 0x0003f07c);
1.1.1.6 root 1963: break;
1964: case 28:
1.1.1.7 ! root 1965: if (t0 & 0x007c0000)
1.1.1.6 root 1966: return;
1.1.1.7 ! root 1967: env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (t0 & 0x00000f83) |
! 1968: ((t0 & 0x4) << 22);
1.1.1.6 root 1969: break;
1970: case 31:
1.1.1.7 ! root 1971: if (t0 & 0x007c0000)
1.1.1.6 root 1972: return;
1.1.1.7 ! root 1973: env->active_fpu.fcr31 = t0;
1.1.1.6 root 1974: break;
1975: default:
1976: return;
1977: }
1978: /* set rounding mode */
1979: RESTORE_ROUNDING_MODE;
1.1.1.7 ! root 1980: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 1981: if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
1.1.1.6 root 1982: do_raise_exception(EXCP_FPE);
1983: }
1984:
1.1.1.7 ! root 1985: static inline char ieee_ex_to_mips(char xcpt)
1.1.1.6 root 1986: {
1987: return (xcpt & float_flag_inexact) >> 5 |
1988: (xcpt & float_flag_underflow) >> 3 |
1989: (xcpt & float_flag_overflow) >> 1 |
1990: (xcpt & float_flag_divbyzero) << 1 |
1991: (xcpt & float_flag_invalid) << 4;
1992: }
1993:
1.1.1.7 ! root 1994: static inline char mips_ex_to_ieee(char xcpt)
1.1.1.6 root 1995: {
1996: return (xcpt & FP_INEXACT) << 5 |
1997: (xcpt & FP_UNDERFLOW) << 3 |
1998: (xcpt & FP_OVERFLOW) << 1 |
1999: (xcpt & FP_DIV0) >> 1 |
2000: (xcpt & FP_INVALID) >> 4;
2001: }
2002:
1.1.1.7 ! root 2003: static inline void update_fcr31(void)
1.1.1.6 root 2004: {
1.1.1.7 ! root 2005: int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6 root 2006:
1.1.1.7 ! root 2007: SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
! 2008: if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp)
1.1.1.6 root 2009: do_raise_exception(EXCP_FPE);
2010: else
1.1.1.7 ! root 2011: UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
1.1.1.6 root 2012: }
2013:
1.1.1.7 ! root 2014: /* Float support.
! 2015: Single precition routines have a "s" suffix, double precision a
! 2016: "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
! 2017: paired single lower "pl", paired single upper "pu". */
! 2018:
! 2019: /* unary operations, modifying fp status */
! 2020: uint64_t do_float_sqrt_d(uint64_t fdt0)
! 2021: {
! 2022: return float64_sqrt(fdt0, &env->active_fpu.fp_status);
! 2023: }
1.1.1.6 root 2024:
1.1.1.7 ! root 2025: uint32_t do_float_sqrt_s(uint32_t fst0)
1.1.1.6 root 2026: {
1.1.1.7 ! root 2027: return float32_sqrt(fst0, &env->active_fpu.fp_status);
! 2028: }
! 2029:
! 2030: uint64_t do_float_cvtd_s(uint32_t fst0)
! 2031: {
! 2032: uint64_t fdt2;
! 2033:
! 2034: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2035: fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2036: update_fcr31();
1.1.1.7 ! root 2037: return fdt2;
1.1.1.6 root 2038: }
1.1.1.7 ! root 2039:
! 2040: uint64_t do_float_cvtd_w(uint32_t wt0)
1.1.1.6 root 2041: {
1.1.1.7 ! root 2042: uint64_t fdt2;
! 2043:
! 2044: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2045: fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
1.1.1.6 root 2046: update_fcr31();
1.1.1.7 ! root 2047: return fdt2;
1.1.1.6 root 2048: }
1.1.1.7 ! root 2049:
! 2050: uint64_t do_float_cvtd_l(uint64_t dt0)
1.1.1.6 root 2051: {
1.1.1.7 ! root 2052: uint64_t fdt2;
! 2053:
! 2054: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2055: fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
1.1.1.6 root 2056: update_fcr31();
1.1.1.7 ! root 2057: return fdt2;
1.1.1.6 root 2058: }
1.1.1.7 ! root 2059:
! 2060: uint64_t do_float_cvtl_d(uint64_t fdt0)
1.1.1.6 root 2061: {
1.1.1.7 ! root 2062: uint64_t dt2;
! 2063:
! 2064: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2065: dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2066: update_fcr31();
1.1.1.7 ! root 2067: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2068: dt2 = FLOAT_SNAN64;
! 2069: return dt2;
1.1.1.6 root 2070: }
1.1.1.7 ! root 2071:
! 2072: uint64_t do_float_cvtl_s(uint32_t fst0)
1.1.1.6 root 2073: {
1.1.1.7 ! root 2074: uint64_t dt2;
! 2075:
! 2076: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2077: dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2078: update_fcr31();
1.1.1.7 ! root 2079: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2080: dt2 = FLOAT_SNAN64;
! 2081: return dt2;
1.1.1.6 root 2082: }
2083:
1.1.1.7 ! root 2084: uint64_t do_float_cvtps_pw(uint64_t dt0)
1.1.1.6 root 2085: {
1.1.1.7 ! root 2086: uint32_t fst2;
! 2087: uint32_t fsth2;
! 2088:
! 2089: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2090: fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
! 2091: fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6 root 2092: update_fcr31();
1.1.1.7 ! root 2093: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2094: }
1.1.1.7 ! root 2095:
! 2096: uint64_t do_float_cvtpw_ps(uint64_t fdt0)
1.1.1.6 root 2097: {
1.1.1.7 ! root 2098: uint32_t wt2;
! 2099: uint32_t wth2;
! 2100:
! 2101: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2102: wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
! 2103: wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6 root 2104: update_fcr31();
1.1.1.7 ! root 2105: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) {
! 2106: wt2 = FLOAT_SNAN32;
! 2107: wth2 = FLOAT_SNAN32;
! 2108: }
! 2109: return ((uint64_t)wth2 << 32) | wt2;
1.1.1.6 root 2110: }
1.1.1.7 ! root 2111:
! 2112: uint32_t do_float_cvts_d(uint64_t fdt0)
1.1.1.6 root 2113: {
1.1.1.7 ! root 2114: uint32_t fst2;
! 2115:
! 2116: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2117: fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2118: update_fcr31();
1.1.1.7 ! root 2119: return fst2;
1.1.1.6 root 2120: }
1.1.1.7 ! root 2121:
! 2122: uint32_t do_float_cvts_w(uint32_t wt0)
1.1.1.6 root 2123: {
1.1.1.7 ! root 2124: uint32_t fst2;
! 2125:
! 2126: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2127: fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
1.1.1.6 root 2128: update_fcr31();
1.1.1.7 ! root 2129: return fst2;
1.1.1.6 root 2130: }
1.1.1.7 ! root 2131:
! 2132: uint32_t do_float_cvts_l(uint64_t dt0)
1.1.1.6 root 2133: {
1.1.1.7 ! root 2134: uint32_t fst2;
! 2135:
! 2136: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2137: fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
1.1.1.6 root 2138: update_fcr31();
1.1.1.7 ! root 2139: return fst2;
1.1.1.6 root 2140: }
1.1.1.7 ! root 2141:
! 2142: uint32_t do_float_cvts_pl(uint32_t wt0)
1.1.1.6 root 2143: {
1.1.1.7 ! root 2144: uint32_t wt2;
! 2145:
! 2146: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2147: wt2 = wt0;
1.1.1.6 root 2148: update_fcr31();
1.1.1.7 ! root 2149: return wt2;
1.1.1.6 root 2150: }
1.1.1.7 ! root 2151:
! 2152: uint32_t do_float_cvts_pu(uint32_t wth0)
1.1.1.6 root 2153: {
1.1.1.7 ! root 2154: uint32_t wt2;
! 2155:
! 2156: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2157: wt2 = wth0;
1.1.1.6 root 2158: update_fcr31();
1.1.1.7 ! root 2159: return wt2;
1.1.1.6 root 2160: }
1.1.1.7 ! root 2161:
! 2162: uint32_t do_float_cvtw_s(uint32_t fst0)
1.1.1.6 root 2163: {
1.1.1.7 ! root 2164: uint32_t wt2;
! 2165:
! 2166: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2167: wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2168: update_fcr31();
1.1.1.7 ! root 2169: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2170: wt2 = FLOAT_SNAN32;
! 2171: return wt2;
1.1.1.6 root 2172: }
1.1.1.7 ! root 2173:
! 2174: uint32_t do_float_cvtw_d(uint64_t fdt0)
1.1.1.6 root 2175: {
1.1.1.7 ! root 2176: uint32_t wt2;
! 2177:
! 2178: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2179: wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2180: update_fcr31();
1.1.1.7 ! root 2181: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2182: wt2 = FLOAT_SNAN32;
! 2183: return wt2;
1.1.1.6 root 2184: }
2185:
1.1.1.7 ! root 2186: uint64_t do_float_roundl_d(uint64_t fdt0)
1.1.1.6 root 2187: {
1.1.1.7 ! root 2188: uint64_t dt2;
! 2189:
! 2190: set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
! 2191: dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2192: RESTORE_ROUNDING_MODE;
2193: update_fcr31();
1.1.1.7 ! root 2194: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2195: dt2 = FLOAT_SNAN64;
! 2196: return dt2;
1.1.1.6 root 2197: }
1.1.1.7 ! root 2198:
! 2199: uint64_t do_float_roundl_s(uint32_t fst0)
1.1.1.6 root 2200: {
1.1.1.7 ! root 2201: uint64_t dt2;
! 2202:
! 2203: set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
! 2204: dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2205: RESTORE_ROUNDING_MODE;
2206: update_fcr31();
1.1.1.7 ! root 2207: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2208: dt2 = FLOAT_SNAN64;
! 2209: return dt2;
1.1.1.6 root 2210: }
1.1.1.7 ! root 2211:
! 2212: uint32_t do_float_roundw_d(uint64_t fdt0)
1.1.1.6 root 2213: {
1.1.1.7 ! root 2214: uint32_t wt2;
! 2215:
! 2216: set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
! 2217: wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2218: RESTORE_ROUNDING_MODE;
2219: update_fcr31();
1.1.1.7 ! root 2220: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2221: wt2 = FLOAT_SNAN32;
! 2222: return wt2;
1.1.1.6 root 2223: }
1.1.1.7 ! root 2224:
! 2225: uint32_t do_float_roundw_s(uint32_t fst0)
1.1.1.6 root 2226: {
1.1.1.7 ! root 2227: uint32_t wt2;
! 2228:
! 2229: set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
! 2230: wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2231: RESTORE_ROUNDING_MODE;
2232: update_fcr31();
1.1.1.7 ! root 2233: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2234: wt2 = FLOAT_SNAN32;
! 2235: return wt2;
1.1.1.6 root 2236: }
2237:
1.1.1.7 ! root 2238: uint64_t do_float_truncl_d(uint64_t fdt0)
1.1.1.6 root 2239: {
1.1.1.7 ! root 2240: uint64_t dt2;
! 2241:
! 2242: dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2243: update_fcr31();
1.1.1.7 ! root 2244: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2245: dt2 = FLOAT_SNAN64;
! 2246: return dt2;
1.1.1.6 root 2247: }
1.1.1.7 ! root 2248:
! 2249: uint64_t do_float_truncl_s(uint32_t fst0)
1.1.1.6 root 2250: {
1.1.1.7 ! root 2251: uint64_t dt2;
! 2252:
! 2253: dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2254: update_fcr31();
1.1.1.7 ! root 2255: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2256: dt2 = FLOAT_SNAN64;
! 2257: return dt2;
1.1.1.6 root 2258: }
1.1.1.7 ! root 2259:
! 2260: uint32_t do_float_truncw_d(uint64_t fdt0)
1.1.1.6 root 2261: {
1.1.1.7 ! root 2262: uint32_t wt2;
! 2263:
! 2264: wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2265: update_fcr31();
1.1.1.7 ! root 2266: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2267: wt2 = FLOAT_SNAN32;
! 2268: return wt2;
1.1.1.6 root 2269: }
1.1.1.7 ! root 2270:
! 2271: uint32_t do_float_truncw_s(uint32_t fst0)
1.1.1.6 root 2272: {
1.1.1.7 ! root 2273: uint32_t wt2;
! 2274:
! 2275: wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2276: update_fcr31();
1.1.1.7 ! root 2277: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2278: wt2 = FLOAT_SNAN32;
! 2279: return wt2;
1.1.1.6 root 2280: }
2281:
1.1.1.7 ! root 2282: uint64_t do_float_ceill_d(uint64_t fdt0)
1.1.1.6 root 2283: {
1.1.1.7 ! root 2284: uint64_t dt2;
! 2285:
! 2286: set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
! 2287: dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2288: RESTORE_ROUNDING_MODE;
2289: update_fcr31();
1.1.1.7 ! root 2290: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2291: dt2 = FLOAT_SNAN64;
! 2292: return dt2;
1.1.1.6 root 2293: }
1.1.1.7 ! root 2294:
! 2295: uint64_t do_float_ceill_s(uint32_t fst0)
1.1.1.6 root 2296: {
1.1.1.7 ! root 2297: uint64_t dt2;
! 2298:
! 2299: set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
! 2300: dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2301: RESTORE_ROUNDING_MODE;
2302: update_fcr31();
1.1.1.7 ! root 2303: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2304: dt2 = FLOAT_SNAN64;
! 2305: return dt2;
1.1.1.6 root 2306: }
1.1.1.7 ! root 2307:
! 2308: uint32_t do_float_ceilw_d(uint64_t fdt0)
1.1.1.6 root 2309: {
1.1.1.7 ! root 2310: uint32_t wt2;
! 2311:
! 2312: set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
! 2313: wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2314: RESTORE_ROUNDING_MODE;
2315: update_fcr31();
1.1.1.7 ! root 2316: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2317: wt2 = FLOAT_SNAN32;
! 2318: return wt2;
1.1.1.6 root 2319: }
1.1.1.7 ! root 2320:
! 2321: uint32_t do_float_ceilw_s(uint32_t fst0)
1.1.1.6 root 2322: {
1.1.1.7 ! root 2323: uint32_t wt2;
! 2324:
! 2325: set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
! 2326: wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2327: RESTORE_ROUNDING_MODE;
2328: update_fcr31();
1.1.1.7 ! root 2329: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2330: wt2 = FLOAT_SNAN32;
! 2331: return wt2;
1.1.1.6 root 2332: }
2333:
1.1.1.7 ! root 2334: uint64_t do_float_floorl_d(uint64_t fdt0)
1.1.1.6 root 2335: {
1.1.1.7 ! root 2336: uint64_t dt2;
! 2337:
! 2338: set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
! 2339: dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2340: RESTORE_ROUNDING_MODE;
2341: update_fcr31();
1.1.1.7 ! root 2342: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2343: dt2 = FLOAT_SNAN64;
! 2344: return dt2;
1.1.1.6 root 2345: }
1.1.1.7 ! root 2346:
! 2347: uint64_t do_float_floorl_s(uint32_t fst0)
1.1.1.6 root 2348: {
1.1.1.7 ! root 2349: uint64_t dt2;
! 2350:
! 2351: set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
! 2352: dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2353: RESTORE_ROUNDING_MODE;
2354: update_fcr31();
1.1.1.7 ! root 2355: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2356: dt2 = FLOAT_SNAN64;
! 2357: return dt2;
1.1.1.6 root 2358: }
1.1.1.7 ! root 2359:
! 2360: uint32_t do_float_floorw_d(uint64_t fdt0)
1.1.1.6 root 2361: {
1.1.1.7 ! root 2362: uint32_t wt2;
! 2363:
! 2364: set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
! 2365: wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2366: RESTORE_ROUNDING_MODE;
2367: update_fcr31();
1.1.1.7 ! root 2368: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2369: wt2 = FLOAT_SNAN32;
! 2370: return wt2;
1.1.1.6 root 2371: }
1.1.1.7 ! root 2372:
! 2373: uint32_t do_float_floorw_s(uint32_t fst0)
1.1.1.6 root 2374: {
1.1.1.7 ! root 2375: uint32_t wt2;
! 2376:
! 2377: set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
! 2378: wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2379: RESTORE_ROUNDING_MODE;
2380: update_fcr31();
1.1.1.7 ! root 2381: if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
! 2382: wt2 = FLOAT_SNAN32;
! 2383: return wt2;
! 2384: }
! 2385:
! 2386: /* unary operations, not modifying fp status */
! 2387: #define FLOAT_UNOP(name) \
! 2388: uint64_t do_float_ ## name ## _d(uint64_t fdt0) \
! 2389: { \
! 2390: return float64_ ## name(fdt0); \
! 2391: } \
! 2392: uint32_t do_float_ ## name ## _s(uint32_t fst0) \
! 2393: { \
! 2394: return float32_ ## name(fst0); \
! 2395: } \
! 2396: uint64_t do_float_ ## name ## _ps(uint64_t fdt0) \
! 2397: { \
! 2398: uint32_t wt0; \
! 2399: uint32_t wth0; \
! 2400: \
! 2401: wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \
! 2402: wth0 = float32_ ## name(fdt0 >> 32); \
! 2403: return ((uint64_t)wth0 << 32) | wt0; \
! 2404: }
! 2405: FLOAT_UNOP(abs)
! 2406: FLOAT_UNOP(chs)
! 2407: #undef FLOAT_UNOP
1.1.1.6 root 2408:
2409: /* MIPS specific unary operations */
1.1.1.7 ! root 2410: uint64_t do_float_recip_d(uint64_t fdt0)
1.1.1.6 root 2411: {
1.1.1.7 ! root 2412: uint64_t fdt2;
! 2413:
! 2414: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2415: fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2416: update_fcr31();
1.1.1.7 ! root 2417: return fdt2;
1.1.1.6 root 2418: }
1.1.1.7 ! root 2419:
! 2420: uint32_t do_float_recip_s(uint32_t fst0)
1.1.1.6 root 2421: {
1.1.1.7 ! root 2422: uint32_t fst2;
! 2423:
! 2424: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2425: fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2426: update_fcr31();
1.1.1.7 ! root 2427: return fst2;
1.1.1.6 root 2428: }
2429:
1.1.1.7 ! root 2430: uint64_t do_float_rsqrt_d(uint64_t fdt0)
1.1.1.6 root 2431: {
1.1.1.7 ! root 2432: uint64_t fdt2;
! 2433:
! 2434: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2435: fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
! 2436: fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6 root 2437: update_fcr31();
1.1.1.7 ! root 2438: return fdt2;
1.1.1.6 root 2439: }
1.1.1.7 ! root 2440:
! 2441: uint32_t do_float_rsqrt_s(uint32_t fst0)
1.1.1.6 root 2442: {
1.1.1.7 ! root 2443: uint32_t fst2;
! 2444:
! 2445: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2446: fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
! 2447: fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6 root 2448: update_fcr31();
1.1.1.7 ! root 2449: return fst2;
1.1.1.6 root 2450: }
2451:
1.1.1.7 ! root 2452: uint64_t do_float_recip1_d(uint64_t fdt0)
1.1.1.6 root 2453: {
1.1.1.7 ! root 2454: uint64_t fdt2;
! 2455:
! 2456: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2457: fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6 root 2458: update_fcr31();
1.1.1.7 ! root 2459: return fdt2;
1.1.1.6 root 2460: }
1.1.1.7 ! root 2461:
! 2462: uint32_t do_float_recip1_s(uint32_t fst0)
1.1.1.6 root 2463: {
1.1.1.7 ! root 2464: uint32_t fst2;
! 2465:
! 2466: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2467: fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6 root 2468: update_fcr31();
1.1.1.7 ! root 2469: return fst2;
1.1.1.6 root 2470: }
1.1.1.7 ! root 2471:
! 2472: uint64_t do_float_recip1_ps(uint64_t fdt0)
1.1.1.6 root 2473: {
1.1.1.7 ! root 2474: uint32_t fst2;
! 2475: uint32_t fsth2;
! 2476:
! 2477: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2478: fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
! 2479: fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6 root 2480: update_fcr31();
1.1.1.7 ! root 2481: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2482: }
2483:
1.1.1.7 ! root 2484: uint64_t do_float_rsqrt1_d(uint64_t fdt0)
1.1.1.6 root 2485: {
1.1.1.7 ! root 2486: uint64_t fdt2;
! 2487:
! 2488: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2489: fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
! 2490: fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6 root 2491: update_fcr31();
1.1.1.7 ! root 2492: return fdt2;
1.1.1.6 root 2493: }
1.1.1.7 ! root 2494:
! 2495: uint32_t do_float_rsqrt1_s(uint32_t fst0)
1.1.1.6 root 2496: {
1.1.1.7 ! root 2497: uint32_t fst2;
! 2498:
! 2499: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2500: fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
! 2501: fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6 root 2502: update_fcr31();
1.1.1.7 ! root 2503: return fst2;
1.1.1.6 root 2504: }
1.1.1.7 ! root 2505:
! 2506: uint64_t do_float_rsqrt1_ps(uint64_t fdt0)
1.1.1.6 root 2507: {
1.1.1.7 ! root 2508: uint32_t fst2;
! 2509: uint32_t fsth2;
! 2510:
! 2511: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2512: fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
! 2513: fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
! 2514: fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
! 2515: fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->active_fpu.fp_status);
1.1.1.6 root 2516: update_fcr31();
1.1.1.7 ! root 2517: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2518: }
2519:
1.1.1.7 ! root 2520: #define FLOAT_OP(name, p) void do_float_##name##_##p(void)
! 2521:
1.1.1.6 root 2522: /* binary operations */
1.1.1.7 ! root 2523: #define FLOAT_BINOP(name) \
! 2524: uint64_t do_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1) \
! 2525: { \
! 2526: uint64_t dt2; \
! 2527: \
! 2528: set_float_exception_flags(0, &env->active_fpu.fp_status); \
! 2529: dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status); \
! 2530: update_fcr31(); \
! 2531: if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \
! 2532: dt2 = FLOAT_QNAN64; \
! 2533: return dt2; \
! 2534: } \
! 2535: \
! 2536: uint32_t do_float_ ## name ## _s(uint32_t fst0, uint32_t fst1) \
! 2537: { \
! 2538: uint32_t wt2; \
! 2539: \
! 2540: set_float_exception_flags(0, &env->active_fpu.fp_status); \
! 2541: wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
1.1.1.6 root 2542: update_fcr31(); \
1.1.1.7 ! root 2543: if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \
! 2544: wt2 = FLOAT_QNAN32; \
! 2545: return wt2; \
! 2546: } \
! 2547: \
! 2548: uint64_t do_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1) \
! 2549: { \
! 2550: uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
! 2551: uint32_t fsth0 = fdt0 >> 32; \
! 2552: uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
! 2553: uint32_t fsth1 = fdt1 >> 32; \
! 2554: uint32_t wt2; \
! 2555: uint32_t wth2; \
! 2556: \
! 2557: set_float_exception_flags(0, &env->active_fpu.fp_status); \
! 2558: wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
! 2559: wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status); \
1.1.1.6 root 2560: update_fcr31(); \
1.1.1.7 ! root 2561: if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { \
! 2562: wt2 = FLOAT_QNAN32; \
! 2563: wth2 = FLOAT_QNAN32; \
! 2564: } \
! 2565: return ((uint64_t)wth2 << 32) | wt2; \
1.1.1.6 root 2566: }
1.1.1.7 ! root 2567:
1.1.1.6 root 2568: FLOAT_BINOP(add)
2569: FLOAT_BINOP(sub)
2570: FLOAT_BINOP(mul)
2571: FLOAT_BINOP(div)
2572: #undef FLOAT_BINOP
2573:
1.1.1.7 ! root 2574: /* ternary operations */
! 2575: #define FLOAT_TERNOP(name1, name2) \
! 2576: uint64_t do_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
! 2577: uint64_t fdt2) \
! 2578: { \
! 2579: fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \
! 2580: return float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \
! 2581: } \
! 2582: \
! 2583: uint32_t do_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
! 2584: uint32_t fst2) \
! 2585: { \
! 2586: fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
! 2587: return float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
! 2588: } \
! 2589: \
! 2590: uint64_t do_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \
! 2591: uint64_t fdt2) \
! 2592: { \
! 2593: uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
! 2594: uint32_t fsth0 = fdt0 >> 32; \
! 2595: uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
! 2596: uint32_t fsth1 = fdt1 >> 32; \
! 2597: uint32_t fst2 = fdt2 & 0XFFFFFFFF; \
! 2598: uint32_t fsth2 = fdt2 >> 32; \
! 2599: \
! 2600: fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
! 2601: fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status); \
! 2602: fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
! 2603: fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status); \
! 2604: return ((uint64_t)fsth2 << 32) | fst2; \
! 2605: }
! 2606:
! 2607: FLOAT_TERNOP(mul, add)
! 2608: FLOAT_TERNOP(mul, sub)
! 2609: #undef FLOAT_TERNOP
! 2610:
! 2611: /* negated ternary operations */
! 2612: #define FLOAT_NTERNOP(name1, name2) \
! 2613: uint64_t do_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
! 2614: uint64_t fdt2) \
! 2615: { \
! 2616: fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \
! 2617: fdt2 = float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \
! 2618: return float64_chs(fdt2); \
! 2619: } \
! 2620: \
! 2621: uint32_t do_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
! 2622: uint32_t fst2) \
! 2623: { \
! 2624: fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
! 2625: fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
! 2626: return float32_chs(fst2); \
! 2627: } \
! 2628: \
! 2629: uint64_t do_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\
! 2630: uint64_t fdt2) \
! 2631: { \
! 2632: uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
! 2633: uint32_t fsth0 = fdt0 >> 32; \
! 2634: uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
! 2635: uint32_t fsth1 = fdt1 >> 32; \
! 2636: uint32_t fst2 = fdt2 & 0XFFFFFFFF; \
! 2637: uint32_t fsth2 = fdt2 >> 32; \
! 2638: \
! 2639: fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
! 2640: fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status); \
! 2641: fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
! 2642: fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status); \
! 2643: fst2 = float32_chs(fst2); \
! 2644: fsth2 = float32_chs(fsth2); \
! 2645: return ((uint64_t)fsth2 << 32) | fst2; \
! 2646: }
! 2647:
! 2648: FLOAT_NTERNOP(mul, add)
! 2649: FLOAT_NTERNOP(mul, sub)
! 2650: #undef FLOAT_NTERNOP
! 2651:
1.1.1.6 root 2652: /* MIPS specific binary operations */
1.1.1.7 ! root 2653: uint64_t do_float_recip2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6 root 2654: {
1.1.1.7 ! root 2655: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2656: fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
! 2657: fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status));
1.1.1.6 root 2658: update_fcr31();
1.1.1.7 ! root 2659: return fdt2;
1.1.1.6 root 2660: }
1.1.1.7 ! root 2661:
! 2662: uint32_t do_float_recip2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6 root 2663: {
1.1.1.7 ! root 2664: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2665: fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
! 2666: fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6 root 2667: update_fcr31();
1.1.1.7 ! root 2668: return fst2;
1.1.1.6 root 2669: }
1.1.1.7 ! root 2670:
! 2671: uint64_t do_float_recip2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6 root 2672: {
1.1.1.7 ! root 2673: uint32_t fst0 = fdt0 & 0XFFFFFFFF;
! 2674: uint32_t fsth0 = fdt0 >> 32;
! 2675: uint32_t fst2 = fdt2 & 0XFFFFFFFF;
! 2676: uint32_t fsth2 = fdt2 >> 32;
! 2677:
! 2678: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2679: fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
! 2680: fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
! 2681: fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
! 2682: fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6 root 2683: update_fcr31();
1.1.1.7 ! root 2684: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2685: }
2686:
1.1.1.7 ! root 2687: uint64_t do_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6 root 2688: {
1.1.1.7 ! root 2689: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2690: fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
! 2691: fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status);
! 2692: fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
1.1.1.6 root 2693: update_fcr31();
1.1.1.7 ! root 2694: return fdt2;
1.1.1.6 root 2695: }
1.1.1.7 ! root 2696:
! 2697: uint32_t do_float_rsqrt2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6 root 2698: {
1.1.1.7 ! root 2699: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2700: fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
! 2701: fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
! 2702: fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6 root 2703: update_fcr31();
1.1.1.7 ! root 2704: return fst2;
1.1.1.6 root 2705: }
1.1.1.7 ! root 2706:
! 2707: uint64_t do_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6 root 2708: {
1.1.1.7 ! root 2709: uint32_t fst0 = fdt0 & 0XFFFFFFFF;
! 2710: uint32_t fsth0 = fdt0 >> 32;
! 2711: uint32_t fst2 = fdt2 & 0XFFFFFFFF;
! 2712: uint32_t fsth2 = fdt2 >> 32;
! 2713:
! 2714: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2715: fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
! 2716: fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
! 2717: fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
! 2718: fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status);
! 2719: fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
! 2720: fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6 root 2721: update_fcr31();
1.1.1.7 ! root 2722: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2723: }
2724:
1.1.1.7 ! root 2725: uint64_t do_float_addr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6 root 2726: {
1.1.1.7 ! root 2727: uint32_t fst0 = fdt0 & 0XFFFFFFFF;
! 2728: uint32_t fsth0 = fdt0 >> 32;
! 2729: uint32_t fst1 = fdt1 & 0XFFFFFFFF;
! 2730: uint32_t fsth1 = fdt1 >> 32;
! 2731: uint32_t fst2;
! 2732: uint32_t fsth2;
! 2733:
! 2734: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2735: fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
! 2736: fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6 root 2737: update_fcr31();
1.1.1.7 ! root 2738: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2739: }
2740:
1.1.1.7 ! root 2741: uint64_t do_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6 root 2742: {
1.1.1.7 ! root 2743: uint32_t fst0 = fdt0 & 0XFFFFFFFF;
! 2744: uint32_t fsth0 = fdt0 >> 32;
! 2745: uint32_t fst1 = fdt1 & 0XFFFFFFFF;
! 2746: uint32_t fsth1 = fdt1 >> 32;
! 2747: uint32_t fst2;
! 2748: uint32_t fsth2;
! 2749:
! 2750: set_float_exception_flags(0, &env->active_fpu.fp_status);
! 2751: fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
! 2752: fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6 root 2753: update_fcr31();
1.1.1.7 ! root 2754: return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6 root 2755: }
2756:
2757: /* compare operations */
1.1.1.7 ! root 2758: #define FOP_COND_D(op, cond) \
! 2759: void do_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
! 2760: { \
! 2761: int c = cond; \
! 2762: update_fcr31(); \
! 2763: if (c) \
! 2764: SET_FP_COND(cc, env->active_fpu); \
! 2765: else \
! 2766: CLEAR_FP_COND(cc, env->active_fpu); \
! 2767: } \
! 2768: void do_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
! 2769: { \
! 2770: int c; \
! 2771: fdt0 = float64_abs(fdt0); \
! 2772: fdt1 = float64_abs(fdt1); \
! 2773: c = cond; \
! 2774: update_fcr31(); \
! 2775: if (c) \
! 2776: SET_FP_COND(cc, env->active_fpu); \
! 2777: else \
! 2778: CLEAR_FP_COND(cc, env->active_fpu); \
1.1.1.6 root 2779: }
2780:
1.1.1.7 ! root 2781: static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
1.1.1.6 root 2782: {
2783: if (float64_is_signaling_nan(a) ||
2784: float64_is_signaling_nan(b) ||
2785: (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
2786: float_raise(float_flag_invalid, status);
2787: return 1;
2788: } else if (float64_is_nan(a) || float64_is_nan(b)) {
2789: return 1;
2790: } else {
2791: return 0;
2792: }
2793: }
2794:
2795: /* NOTE: the comma operator will make "cond" to eval to false,
2796: * but float*_is_unordered() is still called. */
1.1.1.7 ! root 2797: FOP_COND_D(f, (float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status), 0))
! 2798: FOP_COND_D(un, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status))
! 2799: FOP_COND_D(eq, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
! 2800: FOP_COND_D(ueq, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
! 2801: FOP_COND_D(olt, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
! 2802: FOP_COND_D(ult, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
! 2803: FOP_COND_D(ole, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
! 2804: FOP_COND_D(ule, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
1.1.1.6 root 2805: /* NOTE: the comma operator will make "cond" to eval to false,
2806: * but float*_is_unordered() is still called. */
1.1.1.7 ! root 2807: FOP_COND_D(sf, (float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status), 0))
! 2808: FOP_COND_D(ngle,float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status))
! 2809: FOP_COND_D(seq, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
! 2810: FOP_COND_D(ngl, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
! 2811: FOP_COND_D(lt, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
! 2812: FOP_COND_D(nge, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
! 2813: FOP_COND_D(le, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
! 2814: FOP_COND_D(ngt, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
! 2815:
! 2816: #define FOP_COND_S(op, cond) \
! 2817: void do_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
! 2818: { \
! 2819: int c = cond; \
! 2820: update_fcr31(); \
! 2821: if (c) \
! 2822: SET_FP_COND(cc, env->active_fpu); \
! 2823: else \
! 2824: CLEAR_FP_COND(cc, env->active_fpu); \
! 2825: } \
! 2826: void do_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
! 2827: { \
! 2828: int c; \
! 2829: fst0 = float32_abs(fst0); \
! 2830: fst1 = float32_abs(fst1); \
! 2831: c = cond; \
! 2832: update_fcr31(); \
! 2833: if (c) \
! 2834: SET_FP_COND(cc, env->active_fpu); \
! 2835: else \
! 2836: CLEAR_FP_COND(cc, env->active_fpu); \
1.1.1.6 root 2837: }
2838:
1.1.1.7 ! root 2839: static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
1.1.1.6 root 2840: {
2841: if (float32_is_signaling_nan(a) ||
2842: float32_is_signaling_nan(b) ||
2843: (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
2844: float_raise(float_flag_invalid, status);
2845: return 1;
2846: } else if (float32_is_nan(a) || float32_is_nan(b)) {
2847: return 1;
2848: } else {
2849: return 0;
2850: }
2851: }
2852:
2853: /* NOTE: the comma operator will make "cond" to eval to false,
2854: * but float*_is_unordered() is still called. */
1.1.1.7 ! root 2855: FOP_COND_S(f, (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0))
! 2856: FOP_COND_S(un, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status))
! 2857: FOP_COND_S(eq, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
! 2858: FOP_COND_S(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
! 2859: FOP_COND_S(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
! 2860: FOP_COND_S(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
! 2861: FOP_COND_S(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
! 2862: FOP_COND_S(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status))
1.1.1.6 root 2863: /* NOTE: the comma operator will make "cond" to eval to false,
2864: * but float*_is_unordered() is still called. */
1.1.1.7 ! root 2865: FOP_COND_S(sf, (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0))
! 2866: FOP_COND_S(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status))
! 2867: FOP_COND_S(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
! 2868: FOP_COND_S(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
! 2869: FOP_COND_S(lt, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
! 2870: FOP_COND_S(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
! 2871: FOP_COND_S(le, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
! 2872: FOP_COND_S(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status))
! 2873:
! 2874: #define FOP_COND_PS(op, condl, condh) \
! 2875: void do_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
! 2876: { \
! 2877: uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
! 2878: uint32_t fsth0 = float32_abs(fdt0 >> 32); \
! 2879: uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
! 2880: uint32_t fsth1 = float32_abs(fdt1 >> 32); \
! 2881: int cl = condl; \
! 2882: int ch = condh; \
! 2883: \
! 2884: update_fcr31(); \
! 2885: if (cl) \
! 2886: SET_FP_COND(cc, env->active_fpu); \
! 2887: else \
! 2888: CLEAR_FP_COND(cc, env->active_fpu); \
! 2889: if (ch) \
! 2890: SET_FP_COND(cc + 1, env->active_fpu); \
! 2891: else \
! 2892: CLEAR_FP_COND(cc + 1, env->active_fpu); \
! 2893: } \
! 2894: void do_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
! 2895: { \
! 2896: uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
! 2897: uint32_t fsth0 = float32_abs(fdt0 >> 32); \
! 2898: uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
! 2899: uint32_t fsth1 = float32_abs(fdt1 >> 32); \
! 2900: int cl = condl; \
! 2901: int ch = condh; \
! 2902: \
! 2903: update_fcr31(); \
! 2904: if (cl) \
! 2905: SET_FP_COND(cc, env->active_fpu); \
! 2906: else \
! 2907: CLEAR_FP_COND(cc, env->active_fpu); \
! 2908: if (ch) \
! 2909: SET_FP_COND(cc + 1, env->active_fpu); \
! 2910: else \
! 2911: CLEAR_FP_COND(cc + 1, env->active_fpu); \
1.1.1.6 root 2912: }
2913:
2914: /* NOTE: the comma operator will make "cond" to eval to false,
2915: * but float*_is_unordered() is still called. */
1.1.1.7 ! root 2916: FOP_COND_PS(f, (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0),
! 2917: (float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status), 0))
! 2918: FOP_COND_PS(un, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status),
! 2919: float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status))
! 2920: FOP_COND_PS(eq, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
! 2921: !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
! 2922: FOP_COND_PS(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
! 2923: float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
! 2924: FOP_COND_PS(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
! 2925: !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
! 2926: FOP_COND_PS(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
! 2927: float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
! 2928: FOP_COND_PS(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status),
! 2929: !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
! 2930: FOP_COND_PS(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
! 2931: float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
1.1.1.6 root 2932: /* NOTE: the comma operator will make "cond" to eval to false,
2933: * but float*_is_unordered() is still called. */
1.1.1.7 ! root 2934: FOP_COND_PS(sf, (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0),
! 2935: (float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status), 0))
! 2936: FOP_COND_PS(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status),
! 2937: float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status))
! 2938: FOP_COND_PS(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
! 2939: !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
! 2940: FOP_COND_PS(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
! 2941: float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
! 2942: FOP_COND_PS(lt, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
! 2943: !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
! 2944: FOP_COND_PS(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
! 2945: float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
! 2946: FOP_COND_PS(le, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status),
! 2947: !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
! 2948: FOP_COND_PS(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
! 2949: float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.