|
|
1.1 ! root 1: /* ! 2: * Alpha emulation cpu micro-operations helpers for qemu. ! 3: * ! 4: * Copyright (c) 2007 Jocelyn Mayer ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, write to the Free Software ! 18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! 19: */ ! 20: ! 21: #include "exec.h" ! 22: #include "host-utils.h" ! 23: #include "softfloat.h" ! 24: ! 25: #include "op_helper.h" ! 26: ! 27: #define MEMSUFFIX _raw ! 28: #include "op_helper_mem.h" ! 29: ! 30: #if !defined(CONFIG_USER_ONLY) ! 31: #define MEMSUFFIX _kernel ! 32: #include "op_helper_mem.h" ! 33: ! 34: #define MEMSUFFIX _executive ! 35: #include "op_helper_mem.h" ! 36: ! 37: #define MEMSUFFIX _supervisor ! 38: #include "op_helper_mem.h" ! 39: ! 40: #define MEMSUFFIX _user ! 41: #include "op_helper_mem.h" ! 42: ! 43: /* This is used for pal modes */ ! 44: #define MEMSUFFIX _data ! 45: #include "op_helper_mem.h" ! 46: #endif ! 47: ! 48: void helper_tb_flush (void) ! 49: { ! 50: tlb_flush(env, 1); ! 51: } ! 52: ! 53: void cpu_dump_EA (target_ulong EA); ! 54: void helper_print_mem_EA (target_ulong EA) ! 55: { ! 56: cpu_dump_EA(EA); ! 57: } ! 58: ! 59: /*****************************************************************************/ ! 60: /* Exceptions processing helpers */ ! 61: void helper_excp (uint32_t excp, uint32_t error) ! 62: { ! 63: env->exception_index = excp; ! 64: env->error_code = error; ! 65: cpu_loop_exit(); ! 66: } ! 67: ! 68: void helper_amask (void) ! 69: { ! 70: switch (env->implver) { ! 71: case IMPLVER_2106x: ! 72: /* EV4, EV45, LCA, LCA45 & EV5 */ ! 73: break; ! 74: case IMPLVER_21164: ! 75: case IMPLVER_21264: ! 76: case IMPLVER_21364: ! 77: T0 &= ~env->amask; ! 78: break; ! 79: } ! 80: } ! 81: ! 82: void helper_load_pcc (void) ! 83: { ! 84: /* XXX: TODO */ ! 85: T0 = 0; ! 86: } ! 87: ! 88: void helper_load_implver (void) ! 89: { ! 90: T0 = env->implver; ! 91: } ! 92: ! 93: void helper_load_fpcr (void) ! 94: { ! 95: T0 = 0; ! 96: #ifdef CONFIG_SOFTFLOAT ! 97: T0 |= env->fp_status.float_exception_flags << 52; ! 98: if (env->fp_status.float_exception_flags) ! 99: T0 |= 1ULL << 63; ! 100: env->ipr[IPR_EXC_SUM] &= ~0x3E: ! 101: env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1; ! 102: #endif ! 103: switch (env->fp_status.float_rounding_mode) { ! 104: case float_round_nearest_even: ! 105: T0 |= 2ULL << 58; ! 106: break; ! 107: case float_round_down: ! 108: T0 |= 1ULL << 58; ! 109: break; ! 110: case float_round_up: ! 111: T0 |= 3ULL << 58; ! 112: break; ! 113: case float_round_to_zero: ! 114: break; ! 115: } ! 116: } ! 117: ! 118: void helper_store_fpcr (void) ! 119: { ! 120: #ifdef CONFIG_SOFTFLOAT ! 121: set_float_exception_flags((T0 >> 52) & 0x3F, &FP_STATUS); ! 122: #endif ! 123: switch ((T0 >> 58) & 3) { ! 124: case 0: ! 125: set_float_rounding_mode(float_round_to_zero, &FP_STATUS); ! 126: break; ! 127: case 1: ! 128: set_float_rounding_mode(float_round_down, &FP_STATUS); ! 129: break; ! 130: case 2: ! 131: set_float_rounding_mode(float_round_nearest_even, &FP_STATUS); ! 132: break; ! 133: case 3: ! 134: set_float_rounding_mode(float_round_up, &FP_STATUS); ! 135: break; ! 136: } ! 137: } ! 138: ! 139: void helper_load_irf (void) ! 140: { ! 141: /* XXX: TODO */ ! 142: T0 = 0; ! 143: } ! 144: ! 145: void helper_set_irf (void) ! 146: { ! 147: /* XXX: TODO */ ! 148: } ! 149: ! 150: void helper_clear_irf (void) ! 151: { ! 152: /* XXX: TODO */ ! 153: } ! 154: ! 155: void helper_addqv (void) ! 156: { ! 157: T2 = T0; ! 158: T0 += T1; ! 159: if (unlikely((T2 ^ T1 ^ (-1ULL)) & (T2 ^ T0) & (1ULL << 63))) { ! 160: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); ! 161: } ! 162: } ! 163: ! 164: void helper_addlv (void) ! 165: { ! 166: T2 = T0; ! 167: T0 = (uint32_t)(T0 + T1); ! 168: if (unlikely((T2 ^ T1 ^ (-1UL)) & (T2 ^ T0) & (1UL << 31))) { ! 169: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); ! 170: } ! 171: } ! 172: ! 173: void helper_subqv (void) ! 174: { ! 175: T2 = T0; ! 176: T0 -= T1; ! 177: if (unlikely(((~T2) ^ T0 ^ (-1ULL)) & ((~T2) ^ T1) & (1ULL << 63))) { ! 178: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); ! 179: } ! 180: } ! 181: ! 182: void helper_sublv (void) ! 183: { ! 184: T2 = T0; ! 185: T0 = (uint32_t)(T0 - T1); ! 186: if (unlikely(((~T2) ^ T0 ^ (-1UL)) & ((~T2) ^ T1) & (1UL << 31))) { ! 187: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); ! 188: } ! 189: } ! 190: ! 191: void helper_mullv (void) ! 192: { ! 193: int64_t res = (int64_t)T0 * (int64_t)T1; ! 194: ! 195: if (unlikely((int32_t)res != res)) { ! 196: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); ! 197: } ! 198: T0 = (int64_t)((int32_t)res); ! 199: } ! 200: ! 201: void helper_mulqv () ! 202: { ! 203: uint64_t tl, th; ! 204: ! 205: muls64(&tl, &th, T0, T1); ! 206: /* If th != 0 && th != -1, then we had an overflow */ ! 207: if (unlikely((th + 1) > 1)) { ! 208: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); ! 209: } ! 210: T0 = tl; ! 211: } ! 212: ! 213: void helper_ctpop (void) ! 214: { ! 215: T0 = ctpop64(T0); ! 216: } ! 217: ! 218: void helper_ctlz (void) ! 219: { ! 220: T0 = clz64(T0); ! 221: } ! 222: ! 223: void helper_cttz (void) ! 224: { ! 225: T0 = ctz64(T0); ! 226: } ! 227: ! 228: static always_inline uint64_t byte_zap (uint64_t op, uint8_t mskb) ! 229: { ! 230: uint64_t mask; ! 231: ! 232: mask = 0; ! 233: mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL; ! 234: mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL; ! 235: mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL; ! 236: mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL; ! 237: mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL; ! 238: mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL; ! 239: mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL; ! 240: mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL; ! 241: ! 242: return op & ~mask; ! 243: } ! 244: ! 245: void helper_mskbl (void) ! 246: { ! 247: T0 = byte_zap(T0, 0x01 << (T1 & 7)); ! 248: } ! 249: ! 250: void helper_extbl (void) ! 251: { ! 252: T0 >>= (T1 & 7) * 8; ! 253: T0 = byte_zap(T0, 0xFE); ! 254: } ! 255: ! 256: void helper_insbl (void) ! 257: { ! 258: T0 <<= (T1 & 7) * 8; ! 259: T0 = byte_zap(T0, ~(0x01 << (T1 & 7))); ! 260: } ! 261: ! 262: void helper_mskwl (void) ! 263: { ! 264: T0 = byte_zap(T0, 0x03 << (T1 & 7)); ! 265: } ! 266: ! 267: void helper_extwl (void) ! 268: { ! 269: T0 >>= (T1 & 7) * 8; ! 270: T0 = byte_zap(T0, 0xFC); ! 271: } ! 272: ! 273: void helper_inswl (void) ! 274: { ! 275: T0 <<= (T1 & 7) * 8; ! 276: T0 = byte_zap(T0, ~(0x03 << (T1 & 7))); ! 277: } ! 278: ! 279: void helper_mskll (void) ! 280: { ! 281: T0 = byte_zap(T0, 0x0F << (T1 & 7)); ! 282: } ! 283: ! 284: void helper_extll (void) ! 285: { ! 286: T0 >>= (T1 & 7) * 8; ! 287: T0 = byte_zap(T0, 0xF0); ! 288: } ! 289: ! 290: void helper_insll (void) ! 291: { ! 292: T0 <<= (T1 & 7) * 8; ! 293: T0 = byte_zap(T0, ~(0x0F << (T1 & 7))); ! 294: } ! 295: ! 296: void helper_zap (void) ! 297: { ! 298: T0 = byte_zap(T0, T1); ! 299: } ! 300: ! 301: void helper_zapnot (void) ! 302: { ! 303: T0 = byte_zap(T0, ~T1); ! 304: } ! 305: ! 306: void helper_mskql (void) ! 307: { ! 308: T0 = byte_zap(T0, 0xFF << (T1 & 7)); ! 309: } ! 310: ! 311: void helper_extql (void) ! 312: { ! 313: T0 >>= (T1 & 7) * 8; ! 314: T0 = byte_zap(T0, 0x00); ! 315: } ! 316: ! 317: void helper_insql (void) ! 318: { ! 319: T0 <<= (T1 & 7) * 8; ! 320: T0 = byte_zap(T0, ~(0xFF << (T1 & 7))); ! 321: } ! 322: ! 323: void helper_mskwh (void) ! 324: { ! 325: T0 = byte_zap(T0, (0x03 << (T1 & 7)) >> 8); ! 326: } ! 327: ! 328: void helper_inswh (void) ! 329: { ! 330: T0 >>= 64 - ((T1 & 7) * 8); ! 331: T0 = byte_zap(T0, ~((0x03 << (T1 & 7)) >> 8)); ! 332: } ! 333: ! 334: void helper_extwh (void) ! 335: { ! 336: T0 <<= 64 - ((T1 & 7) * 8); ! 337: T0 = byte_zap(T0, ~0x07); ! 338: } ! 339: ! 340: void helper_msklh (void) ! 341: { ! 342: T0 = byte_zap(T0, (0x0F << (T1 & 7)) >> 8); ! 343: } ! 344: ! 345: void helper_inslh (void) ! 346: { ! 347: T0 >>= 64 - ((T1 & 7) * 8); ! 348: T0 = byte_zap(T0, ~((0x0F << (T1 & 7)) >> 8)); ! 349: } ! 350: ! 351: void helper_extlh (void) ! 352: { ! 353: T0 <<= 64 - ((T1 & 7) * 8); ! 354: T0 = byte_zap(T0, ~0x0F); ! 355: } ! 356: ! 357: void helper_mskqh (void) ! 358: { ! 359: T0 = byte_zap(T0, (0xFF << (T1 & 7)) >> 8); ! 360: } ! 361: ! 362: void helper_insqh (void) ! 363: { ! 364: T0 >>= 64 - ((T1 & 7) * 8); ! 365: T0 = byte_zap(T0, ~((0xFF << (T1 & 7)) >> 8)); ! 366: } ! 367: ! 368: void helper_extqh (void) ! 369: { ! 370: T0 <<= 64 - ((T1 & 7) * 8); ! 371: T0 = byte_zap(T0, 0x00); ! 372: } ! 373: ! 374: void helper_cmpbge (void) ! 375: { ! 376: uint8_t opa, opb, res; ! 377: int i; ! 378: ! 379: res = 0; ! 380: for (i = 0; i < 7; i++) { ! 381: opa = T0 >> (i * 8); ! 382: opb = T1 >> (i * 8); ! 383: if (opa >= opb) ! 384: res |= 1 << i; ! 385: } ! 386: T0 = res; ! 387: } ! 388: ! 389: void helper_cmov_fir (int freg) ! 390: { ! 391: if (FT0 != 0) ! 392: env->fir[freg] = FT1; ! 393: } ! 394: ! 395: void helper_sqrts (void) ! 396: { ! 397: FT0 = float32_sqrt(FT0, &FP_STATUS); ! 398: } ! 399: ! 400: void helper_cpys (void) ! 401: { ! 402: union { ! 403: double d; ! 404: uint64_t i; ! 405: } p, q, r; ! 406: ! 407: p.d = FT0; ! 408: q.d = FT1; ! 409: r.i = p.i & 0x8000000000000000ULL; ! 410: r.i |= q.i & ~0x8000000000000000ULL; ! 411: FT0 = r.d; ! 412: } ! 413: ! 414: void helper_cpysn (void) ! 415: { ! 416: union { ! 417: double d; ! 418: uint64_t i; ! 419: } p, q, r; ! 420: ! 421: p.d = FT0; ! 422: q.d = FT1; ! 423: r.i = (~p.i) & 0x8000000000000000ULL; ! 424: r.i |= q.i & ~0x8000000000000000ULL; ! 425: FT0 = r.d; ! 426: } ! 427: ! 428: void helper_cpyse (void) ! 429: { ! 430: union { ! 431: double d; ! 432: uint64_t i; ! 433: } p, q, r; ! 434: ! 435: p.d = FT0; ! 436: q.d = FT1; ! 437: r.i = p.i & 0xFFF0000000000000ULL; ! 438: r.i |= q.i & ~0xFFF0000000000000ULL; ! 439: FT0 = r.d; ! 440: } ! 441: ! 442: void helper_itofs (void) ! 443: { ! 444: union { ! 445: double d; ! 446: uint64_t i; ! 447: } p; ! 448: ! 449: p.d = FT0; ! 450: FT0 = int64_to_float32(p.i, &FP_STATUS); ! 451: } ! 452: ! 453: void helper_ftois (void) ! 454: { ! 455: union { ! 456: double d; ! 457: uint64_t i; ! 458: } p; ! 459: ! 460: p.i = float32_to_int64(FT0, &FP_STATUS); ! 461: FT0 = p.d; ! 462: } ! 463: ! 464: void helper_sqrtt (void) ! 465: { ! 466: FT0 = float64_sqrt(FT0, &FP_STATUS); ! 467: } ! 468: ! 469: void helper_cmptun (void) ! 470: { ! 471: union { ! 472: double d; ! 473: uint64_t i; ! 474: } p; ! 475: ! 476: p.i = 0; ! 477: if (float64_is_nan(FT0) || float64_is_nan(FT1)) ! 478: p.i = 0x4000000000000000ULL; ! 479: FT0 = p.d; ! 480: } ! 481: ! 482: void helper_cmpteq (void) ! 483: { ! 484: union { ! 485: double d; ! 486: uint64_t i; ! 487: } p; ! 488: ! 489: p.i = 0; ! 490: if (float64_eq(FT0, FT1, &FP_STATUS)) ! 491: p.i = 0x4000000000000000ULL; ! 492: FT0 = p.d; ! 493: } ! 494: ! 495: void helper_cmptle (void) ! 496: { ! 497: union { ! 498: double d; ! 499: uint64_t i; ! 500: } p; ! 501: ! 502: p.i = 0; ! 503: if (float64_le(FT0, FT1, &FP_STATUS)) ! 504: p.i = 0x4000000000000000ULL; ! 505: FT0 = p.d; ! 506: } ! 507: ! 508: void helper_cmptlt (void) ! 509: { ! 510: union { ! 511: double d; ! 512: uint64_t i; ! 513: } p; ! 514: ! 515: p.i = 0; ! 516: if (float64_lt(FT0, FT1, &FP_STATUS)) ! 517: p.i = 0x4000000000000000ULL; ! 518: FT0 = p.d; ! 519: } ! 520: ! 521: void helper_itoft (void) ! 522: { ! 523: union { ! 524: double d; ! 525: uint64_t i; ! 526: } p; ! 527: ! 528: p.d = FT0; ! 529: FT0 = int64_to_float64(p.i, &FP_STATUS); ! 530: } ! 531: ! 532: void helper_ftoit (void) ! 533: { ! 534: union { ! 535: double d; ! 536: uint64_t i; ! 537: } p; ! 538: ! 539: p.i = float64_to_int64(FT0, &FP_STATUS); ! 540: FT0 = p.d; ! 541: } ! 542: ! 543: static always_inline int vaxf_is_valid (float ff) ! 544: { ! 545: union { ! 546: float f; ! 547: uint32_t i; ! 548: } p; ! 549: uint32_t exp, mant; ! 550: ! 551: p.f = ff; ! 552: exp = (p.i >> 23) & 0xFF; ! 553: mant = p.i & 0x007FFFFF; ! 554: if (exp == 0 && ((p.i & 0x80000000) || mant != 0)) { ! 555: /* Reserved operands / Dirty zero */ ! 556: return 0; ! 557: } ! 558: ! 559: return 1; ! 560: } ! 561: ! 562: static always_inline float vaxf_to_ieee32 (float ff) ! 563: { ! 564: union { ! 565: float f; ! 566: uint32_t i; ! 567: } p; ! 568: uint32_t exp; ! 569: ! 570: p.f = ff; ! 571: exp = (p.i >> 23) & 0xFF; ! 572: if (exp < 3) { ! 573: /* Underflow */ ! 574: p.f = 0.0; ! 575: } else { ! 576: p.f *= 0.25; ! 577: } ! 578: ! 579: return p.f; ! 580: } ! 581: ! 582: static always_inline float ieee32_to_vaxf (float fi) ! 583: { ! 584: union { ! 585: float f; ! 586: uint32_t i; ! 587: } p; ! 588: uint32_t exp, mant; ! 589: ! 590: p.f = fi; ! 591: exp = (p.i >> 23) & 0xFF; ! 592: mant = p.i & 0x007FFFFF; ! 593: if (exp == 255) { ! 594: /* NaN or infinity */ ! 595: p.i = 1; ! 596: } else if (exp == 0) { ! 597: if (mant == 0) { ! 598: /* Zero */ ! 599: p.i = 0; ! 600: } else { ! 601: /* Denormalized */ ! 602: p.f *= 2.0; ! 603: } ! 604: } else { ! 605: if (exp >= 253) { ! 606: /* Overflow */ ! 607: p.i = 1; ! 608: } else { ! 609: p.f *= 4.0; ! 610: } ! 611: } ! 612: ! 613: return p.f; ! 614: } ! 615: ! 616: void helper_addf (void) ! 617: { ! 618: float ft0, ft1, ft2; ! 619: ! 620: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { ! 621: /* XXX: TODO */ ! 622: } ! 623: ft0 = vaxf_to_ieee32(FT0); ! 624: ft1 = vaxf_to_ieee32(FT1); ! 625: ft2 = float32_add(ft0, ft1, &FP_STATUS); ! 626: FT0 = ieee32_to_vaxf(ft2); ! 627: } ! 628: ! 629: void helper_subf (void) ! 630: { ! 631: float ft0, ft1, ft2; ! 632: ! 633: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { ! 634: /* XXX: TODO */ ! 635: } ! 636: ft0 = vaxf_to_ieee32(FT0); ! 637: ft1 = vaxf_to_ieee32(FT1); ! 638: ft2 = float32_sub(ft0, ft1, &FP_STATUS); ! 639: FT0 = ieee32_to_vaxf(ft2); ! 640: } ! 641: ! 642: void helper_mulf (void) ! 643: { ! 644: float ft0, ft1, ft2; ! 645: ! 646: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { ! 647: /* XXX: TODO */ ! 648: } ! 649: ft0 = vaxf_to_ieee32(FT0); ! 650: ft1 = vaxf_to_ieee32(FT1); ! 651: ft2 = float32_mul(ft0, ft1, &FP_STATUS); ! 652: FT0 = ieee32_to_vaxf(ft2); ! 653: } ! 654: ! 655: void helper_divf (void) ! 656: { ! 657: float ft0, ft1, ft2; ! 658: ! 659: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { ! 660: /* XXX: TODO */ ! 661: } ! 662: ft0 = vaxf_to_ieee32(FT0); ! 663: ft1 = vaxf_to_ieee32(FT1); ! 664: ft2 = float32_div(ft0, ft1, &FP_STATUS); ! 665: FT0 = ieee32_to_vaxf(ft2); ! 666: } ! 667: ! 668: void helper_sqrtf (void) ! 669: { ! 670: float ft0, ft1; ! 671: ! 672: if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { ! 673: /* XXX: TODO */ ! 674: } ! 675: ft0 = vaxf_to_ieee32(FT0); ! 676: ft1 = float32_sqrt(ft0, &FP_STATUS); ! 677: FT0 = ieee32_to_vaxf(ft1); ! 678: } ! 679: ! 680: void helper_itoff (void) ! 681: { ! 682: /* XXX: TODO */ ! 683: } ! 684: ! 685: static always_inline int vaxg_is_valid (double ff) ! 686: { ! 687: union { ! 688: double f; ! 689: uint64_t i; ! 690: } p; ! 691: uint64_t exp, mant; ! 692: ! 693: p.f = ff; ! 694: exp = (p.i >> 52) & 0x7FF; ! 695: mant = p.i & 0x000FFFFFFFFFFFFFULL; ! 696: if (exp == 0 && ((p.i & 0x8000000000000000ULL) || mant != 0)) { ! 697: /* Reserved operands / Dirty zero */ ! 698: return 0; ! 699: } ! 700: ! 701: return 1; ! 702: } ! 703: ! 704: static always_inline double vaxg_to_ieee64 (double fg) ! 705: { ! 706: union { ! 707: double f; ! 708: uint64_t i; ! 709: } p; ! 710: uint32_t exp; ! 711: ! 712: p.f = fg; ! 713: exp = (p.i >> 52) & 0x7FF; ! 714: if (exp < 3) { ! 715: /* Underflow */ ! 716: p.f = 0.0; ! 717: } else { ! 718: p.f *= 0.25; ! 719: } ! 720: ! 721: return p.f; ! 722: } ! 723: ! 724: static always_inline double ieee64_to_vaxg (double fi) ! 725: { ! 726: union { ! 727: double f; ! 728: uint64_t i; ! 729: } p; ! 730: uint64_t mant; ! 731: uint32_t exp; ! 732: ! 733: p.f = fi; ! 734: exp = (p.i >> 52) & 0x7FF; ! 735: mant = p.i & 0x000FFFFFFFFFFFFFULL; ! 736: if (exp == 255) { ! 737: /* NaN or infinity */ ! 738: p.i = 1; /* VAX dirty zero */ ! 739: } else if (exp == 0) { ! 740: if (mant == 0) { ! 741: /* Zero */ ! 742: p.i = 0; ! 743: } else { ! 744: /* Denormalized */ ! 745: p.f *= 2.0; ! 746: } ! 747: } else { ! 748: if (exp >= 2045) { ! 749: /* Overflow */ ! 750: p.i = 1; /* VAX dirty zero */ ! 751: } else { ! 752: p.f *= 4.0; ! 753: } ! 754: } ! 755: ! 756: return p.f; ! 757: } ! 758: ! 759: void helper_addg (void) ! 760: { ! 761: double ft0, ft1, ft2; ! 762: ! 763: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { ! 764: /* XXX: TODO */ ! 765: } ! 766: ft0 = vaxg_to_ieee64(FT0); ! 767: ft1 = vaxg_to_ieee64(FT1); ! 768: ft2 = float64_add(ft0, ft1, &FP_STATUS); ! 769: FT0 = ieee64_to_vaxg(ft2); ! 770: } ! 771: ! 772: void helper_subg (void) ! 773: { ! 774: double ft0, ft1, ft2; ! 775: ! 776: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { ! 777: /* XXX: TODO */ ! 778: } ! 779: ft0 = vaxg_to_ieee64(FT0); ! 780: ft1 = vaxg_to_ieee64(FT1); ! 781: ft2 = float64_sub(ft0, ft1, &FP_STATUS); ! 782: FT0 = ieee64_to_vaxg(ft2); ! 783: } ! 784: ! 785: void helper_mulg (void) ! 786: { ! 787: double ft0, ft1, ft2; ! 788: ! 789: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { ! 790: /* XXX: TODO */ ! 791: } ! 792: ft0 = vaxg_to_ieee64(FT0); ! 793: ft1 = vaxg_to_ieee64(FT1); ! 794: ft2 = float64_mul(ft0, ft1, &FP_STATUS); ! 795: FT0 = ieee64_to_vaxg(ft2); ! 796: } ! 797: ! 798: void helper_divg (void) ! 799: { ! 800: double ft0, ft1, ft2; ! 801: ! 802: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { ! 803: /* XXX: TODO */ ! 804: } ! 805: ft0 = vaxg_to_ieee64(FT0); ! 806: ft1 = vaxg_to_ieee64(FT1); ! 807: ft2 = float64_div(ft0, ft1, &FP_STATUS); ! 808: FT0 = ieee64_to_vaxg(ft2); ! 809: } ! 810: ! 811: void helper_sqrtg (void) ! 812: { ! 813: double ft0, ft1; ! 814: ! 815: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { ! 816: /* XXX: TODO */ ! 817: } ! 818: ft0 = vaxg_to_ieee64(FT0); ! 819: ft1 = float64_sqrt(ft0, &FP_STATUS); ! 820: FT0 = ieee64_to_vaxg(ft1); ! 821: } ! 822: ! 823: void helper_cmpgeq (void) ! 824: { ! 825: union { ! 826: double d; ! 827: uint64_t u; ! 828: } p; ! 829: double ft0, ft1; ! 830: ! 831: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { ! 832: /* XXX: TODO */ ! 833: } ! 834: ft0 = vaxg_to_ieee64(FT0); ! 835: ft1 = vaxg_to_ieee64(FT1); ! 836: p.u = 0; ! 837: if (float64_eq(ft0, ft1, &FP_STATUS)) ! 838: p.u = 0x4000000000000000ULL; ! 839: FT0 = p.d; ! 840: } ! 841: ! 842: void helper_cmpglt (void) ! 843: { ! 844: union { ! 845: double d; ! 846: uint64_t u; ! 847: } p; ! 848: double ft0, ft1; ! 849: ! 850: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { ! 851: /* XXX: TODO */ ! 852: } ! 853: ft0 = vaxg_to_ieee64(FT0); ! 854: ft1 = vaxg_to_ieee64(FT1); ! 855: p.u = 0; ! 856: if (float64_lt(ft0, ft1, &FP_STATUS)) ! 857: p.u = 0x4000000000000000ULL; ! 858: FT0 = p.d; ! 859: } ! 860: ! 861: void helper_cmpgle (void) ! 862: { ! 863: union { ! 864: double d; ! 865: uint64_t u; ! 866: } p; ! 867: double ft0, ft1; ! 868: ! 869: if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { ! 870: /* XXX: TODO */ ! 871: } ! 872: ft0 = vaxg_to_ieee64(FT0); ! 873: ft1 = vaxg_to_ieee64(FT1); ! 874: p.u = 0; ! 875: if (float64_le(ft0, ft1, &FP_STATUS)) ! 876: p.u = 0x4000000000000000ULL; ! 877: FT0 = p.d; ! 878: } ! 879: ! 880: void helper_cvtqs (void) ! 881: { ! 882: union { ! 883: double d; ! 884: uint64_t u; ! 885: } p; ! 886: ! 887: p.d = FT0; ! 888: FT0 = (float)p.u; ! 889: } ! 890: ! 891: void helper_cvttq (void) ! 892: { ! 893: union { ! 894: double d; ! 895: uint64_t u; ! 896: } p; ! 897: ! 898: p.u = FT0; ! 899: FT0 = p.d; ! 900: } ! 901: ! 902: void helper_cvtqt (void) ! 903: { ! 904: union { ! 905: double d; ! 906: uint64_t u; ! 907: } p; ! 908: ! 909: p.d = FT0; ! 910: FT0 = p.u; ! 911: } ! 912: ! 913: void helper_cvtqf (void) ! 914: { ! 915: union { ! 916: double d; ! 917: uint64_t u; ! 918: } p; ! 919: ! 920: p.d = FT0; ! 921: FT0 = ieee32_to_vaxf(p.u); ! 922: } ! 923: ! 924: void helper_cvtgf (void) ! 925: { ! 926: double ft0; ! 927: ! 928: ft0 = vaxg_to_ieee64(FT0); ! 929: FT0 = ieee32_to_vaxf(ft0); ! 930: } ! 931: ! 932: void helper_cvtgd (void) ! 933: { ! 934: /* XXX: TODO */ ! 935: } ! 936: ! 937: void helper_cvtgq (void) ! 938: { ! 939: union { ! 940: double d; ! 941: uint64_t u; ! 942: } p; ! 943: ! 944: p.u = vaxg_to_ieee64(FT0); ! 945: FT0 = p.d; ! 946: } ! 947: ! 948: void helper_cvtqg (void) ! 949: { ! 950: union { ! 951: double d; ! 952: uint64_t u; ! 953: } p; ! 954: ! 955: p.d = FT0; ! 956: FT0 = ieee64_to_vaxg(p.u); ! 957: } ! 958: ! 959: void helper_cvtdg (void) ! 960: { ! 961: /* XXX: TODO */ ! 962: } ! 963: ! 964: void helper_cvtlq (void) ! 965: { ! 966: union { ! 967: double d; ! 968: uint64_t u; ! 969: } p, q; ! 970: ! 971: p.d = FT0; ! 972: q.u = (p.u >> 29) & 0x3FFFFFFF; ! 973: q.u |= (p.u >> 32); ! 974: q.u = (int64_t)((int32_t)q.u); ! 975: FT0 = q.d; ! 976: } ! 977: ! 978: static always_inline void __helper_cvtql (int s, int v) ! 979: { ! 980: union { ! 981: double d; ! 982: uint64_t u; ! 983: } p, q; ! 984: ! 985: p.d = FT0; ! 986: q.u = ((uint64_t)(p.u & 0xC0000000)) << 32; ! 987: q.u |= ((uint64_t)(p.u & 0x7FFFFFFF)) << 29; ! 988: FT0 = q.d; ! 989: if (v && (int64_t)((int32_t)p.u) != (int64_t)p.u) { ! 990: helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); ! 991: } ! 992: if (s) { ! 993: /* TODO */ ! 994: } ! 995: } ! 996: ! 997: void helper_cvtql (void) ! 998: { ! 999: __helper_cvtql(0, 0); ! 1000: } ! 1001: ! 1002: void helper_cvtqlv (void) ! 1003: { ! 1004: __helper_cvtql(0, 1); ! 1005: } ! 1006: ! 1007: void helper_cvtqlsv (void) ! 1008: { ! 1009: __helper_cvtql(1, 1); ! 1010: } ! 1011: ! 1012: void helper_cmpfeq (void) ! 1013: { ! 1014: if (float64_eq(FT0, FT1, &FP_STATUS)) ! 1015: T0 = 1; ! 1016: else ! 1017: T0 = 0; ! 1018: } ! 1019: ! 1020: void helper_cmpfne (void) ! 1021: { ! 1022: if (float64_eq(FT0, FT1, &FP_STATUS)) ! 1023: T0 = 0; ! 1024: else ! 1025: T0 = 1; ! 1026: } ! 1027: ! 1028: void helper_cmpflt (void) ! 1029: { ! 1030: if (float64_lt(FT0, FT1, &FP_STATUS)) ! 1031: T0 = 1; ! 1032: else ! 1033: T0 = 0; ! 1034: } ! 1035: ! 1036: void helper_cmpfle (void) ! 1037: { ! 1038: if (float64_lt(FT0, FT1, &FP_STATUS)) ! 1039: T0 = 1; ! 1040: else ! 1041: T0 = 0; ! 1042: } ! 1043: ! 1044: void helper_cmpfgt (void) ! 1045: { ! 1046: if (float64_le(FT0, FT1, &FP_STATUS)) ! 1047: T0 = 0; ! 1048: else ! 1049: T0 = 1; ! 1050: } ! 1051: ! 1052: void helper_cmpfge (void) ! 1053: { ! 1054: if (float64_lt(FT0, FT1, &FP_STATUS)) ! 1055: T0 = 0; ! 1056: else ! 1057: T0 = 1; ! 1058: } ! 1059: ! 1060: #if !defined (CONFIG_USER_ONLY) ! 1061: void helper_mfpr (int iprn) ! 1062: { ! 1063: uint64_t val; ! 1064: ! 1065: if (cpu_alpha_mfpr(env, iprn, &val) == 0) ! 1066: T0 = val; ! 1067: } ! 1068: ! 1069: void helper_mtpr (int iprn) ! 1070: { ! 1071: cpu_alpha_mtpr(env, iprn, T0, NULL); ! 1072: } ! 1073: #endif ! 1074: ! 1075: #if defined(HOST_SPARC) || defined(HOST_SPARC64) ! 1076: void helper_reset_FT0 (void) ! 1077: { ! 1078: FT0 = 0; ! 1079: } ! 1080: ! 1081: void helper_reset_FT1 (void) ! 1082: { ! 1083: FT1 = 0; ! 1084: } ! 1085: ! 1086: void helper_reset_FT2 (void) ! 1087: { ! 1088: FT2 = 0; ! 1089: } ! 1090: #endif ! 1091: ! 1092: /*****************************************************************************/ ! 1093: /* Softmmu support */ ! 1094: #if !defined (CONFIG_USER_ONLY) ! 1095: ! 1096: #ifdef __s390__ ! 1097: # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL)) ! 1098: #else ! 1099: # define GETPC() (__builtin_return_address(0)) ! 1100: #endif ! 1101: ! 1102: /* XXX: the two following helpers are pure hacks. ! 1103: * Hopefully, we emulate the PALcode, then we should never see ! 1104: * HW_LD / HW_ST instructions. ! 1105: */ ! 1106: void helper_ld_phys_to_virt (void) ! 1107: { ! 1108: uint64_t tlb_addr, physaddr; ! 1109: int index, mmu_idx; ! 1110: void *retaddr; ! 1111: ! 1112: mmu_idx = cpu_mmu_index(env); ! 1113: index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); ! 1114: redo: ! 1115: tlb_addr = env->tlb_table[mmu_idx][index].addr_read; ! 1116: if ((T0 & TARGET_PAGE_MASK) == ! 1117: (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { ! 1118: physaddr = T0 + env->tlb_table[mmu_idx][index].addend; ! 1119: } else { ! 1120: /* the page is not in the TLB : fill it */ ! 1121: retaddr = GETPC(); ! 1122: tlb_fill(T0, 0, mmu_idx, retaddr); ! 1123: goto redo; ! 1124: } ! 1125: T0 = physaddr; ! 1126: } ! 1127: ! 1128: void helper_st_phys_to_virt (void) ! 1129: { ! 1130: uint64_t tlb_addr, physaddr; ! 1131: int index, mmu_idx; ! 1132: void *retaddr; ! 1133: ! 1134: mmu_idx = cpu_mmu_index(env); ! 1135: index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); ! 1136: redo: ! 1137: tlb_addr = env->tlb_table[mmu_idx][index].addr_write; ! 1138: if ((T0 & TARGET_PAGE_MASK) == ! 1139: (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { ! 1140: physaddr = T0 + env->tlb_table[mmu_idx][index].addend; ! 1141: } else { ! 1142: /* the page is not in the TLB : fill it */ ! 1143: retaddr = GETPC(); ! 1144: tlb_fill(T0, 1, mmu_idx, retaddr); ! 1145: goto redo; ! 1146: } ! 1147: T0 = physaddr; ! 1148: } ! 1149: ! 1150: #define MMUSUFFIX _mmu ! 1151: ! 1152: #define SHIFT 0 ! 1153: #include "softmmu_template.h" ! 1154: ! 1155: #define SHIFT 1 ! 1156: #include "softmmu_template.h" ! 1157: ! 1158: #define SHIFT 2 ! 1159: #include "softmmu_template.h" ! 1160: ! 1161: #define SHIFT 3 ! 1162: #include "softmmu_template.h" ! 1163: ! 1164: /* try to fill the TLB and return an exception if error. If retaddr is ! 1165: NULL, it means that the function was called in C code (i.e. not ! 1166: from generated code or from helper.c) */ ! 1167: /* XXX: fix it to restore all registers */ ! 1168: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) ! 1169: { ! 1170: TranslationBlock *tb; ! 1171: CPUState *saved_env; ! 1172: unsigned long pc; ! 1173: int ret; ! 1174: ! 1175: /* XXX: hack to restore env in all cases, even if not called from ! 1176: generated code */ ! 1177: saved_env = env; ! 1178: env = cpu_single_env; ! 1179: ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); ! 1180: if (!likely(ret == 0)) { ! 1181: if (likely(retaddr)) { ! 1182: /* now we have a real cpu fault */ ! 1183: pc = (unsigned long)retaddr; ! 1184: tb = tb_find_pc(pc); ! 1185: if (likely(tb)) { ! 1186: /* the PC is inside the translated code. It means that we have ! 1187: a virtual CPU fault */ ! 1188: cpu_restore_state(tb, env, pc, NULL); ! 1189: } ! 1190: } ! 1191: /* Exception index and error code are already set */ ! 1192: cpu_loop_exit(); ! 1193: } ! 1194: env = saved_env; ! 1195: } ! 1196: ! 1197: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.