1 /* 2 * MIPS ASE DSP Instruction emulation helpers for QEMU. 3 * 4 * Copyright (c) 2012 Jia Liu <proljc@gmail.com> 5 * Dongxue Zhang <elta.era@gmail.com> 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.1 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, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "cpu.h" 22 #include "exec/helper-proto.h" 23 #include "qemu/bitops.h" 24 25 /* 26 * As the byte ordering doesn't matter, i.e. all columns are treated 27 * identically, these unions can be used directly. 28 */ 29 typedef union { 30 uint8_t ub[4]; 31 int8_t sb[4]; 32 uint16_t uh[2]; 33 int16_t sh[2]; 34 uint32_t uw[1]; 35 int32_t sw[1]; 36 } DSP32Value; 37 38 typedef union { 39 uint8_t ub[8]; 40 int8_t sb[8]; 41 uint16_t uh[4]; 42 int16_t sh[4]; 43 uint32_t uw[2]; 44 int32_t sw[2]; 45 uint64_t ul[1]; 46 int64_t sl[1]; 47 } DSP64Value; 48 49 /*** MIPS DSP internal functions begin ***/ 50 #define MIPSDSP_ABS(x) (((x) >= 0) ? (x) : -(x)) 51 #define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~((a) ^ (b)) & ((a) ^ (c)) & (d)) 52 #define MIPSDSP_OVERFLOW_SUB(a, b, c, d) (((a) ^ (b)) & ((a) ^ (c)) & (d)) 53 54 static inline void set_DSPControl_overflow_flag(uint32_t flag, int position, 55 CPUMIPSState *env) 56 { 57 env->active_tc.DSPControl |= (target_ulong)flag << position; 58 } 59 60 static inline void set_DSPControl_carryflag(bool flag, CPUMIPSState *env) 61 { 62 env->active_tc.DSPControl &= ~(1 << 13); 63 env->active_tc.DSPControl |= flag << 13; 64 } 65 66 static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env) 67 { 68 return (env->active_tc.DSPControl >> 13) & 0x01; 69 } 70 71 static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env) 72 { 73 uint32_t filter; 74 75 filter = ((0x01 << len) - 1) << 24; 76 filter = ~filter; 77 78 env->active_tc.DSPControl &= filter; 79 env->active_tc.DSPControl |= (target_ulong)flag << 24; 80 } 81 82 static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env) 83 { 84 target_ulong dspc; 85 86 dspc = env->active_tc.DSPControl; 87 #ifndef TARGET_MIPS64 88 dspc = dspc & 0xFFFFFFC0; 89 dspc |= (pos & 0x3F); 90 #else 91 dspc = dspc & 0xFFFFFF80; 92 dspc |= (pos & 0x7F); 93 #endif 94 env->active_tc.DSPControl = dspc; 95 } 96 97 static inline uint32_t get_DSPControl_pos(CPUMIPSState *env) 98 { 99 target_ulong dspc; 100 uint32_t pos; 101 102 dspc = env->active_tc.DSPControl; 103 104 #ifndef TARGET_MIPS64 105 pos = dspc & 0x3F; 106 #else 107 pos = dspc & 0x7F; 108 #endif 109 110 return pos; 111 } 112 113 static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env) 114 { 115 env->active_tc.DSPControl &= 0xFFFFBFFF; 116 env->active_tc.DSPControl |= (target_ulong)flag << 14; 117 } 118 119 #define DO_MIPS_SAT_ABS(size) \ 120 static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a, \ 121 CPUMIPSState *env) \ 122 { \ 123 if (a == INT##size##_MIN) { \ 124 set_DSPControl_overflow_flag(1, 20, env); \ 125 return INT##size##_MAX; \ 126 } else { \ 127 return MIPSDSP_ABS(a); \ 128 } \ 129 } 130 DO_MIPS_SAT_ABS(8) 131 DO_MIPS_SAT_ABS(16) 132 DO_MIPS_SAT_ABS(32) 133 #undef DO_MIPS_SAT_ABS 134 135 /* get sum value */ 136 static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env) 137 { 138 int16_t tempI; 139 140 tempI = a + b; 141 142 if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x8000)) { 143 set_DSPControl_overflow_flag(1, 20, env); 144 } 145 146 return tempI; 147 } 148 149 static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b, 150 CPUMIPSState *env) 151 { 152 int16_t tempS; 153 154 tempS = a + b; 155 156 if (MIPSDSP_OVERFLOW_ADD(a, b, tempS, 0x8000)) { 157 if (a > 0) { 158 tempS = 0x7FFF; 159 } else { 160 tempS = 0x8000; 161 } 162 set_DSPControl_overflow_flag(1, 20, env); 163 } 164 165 return tempS; 166 } 167 168 static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b, 169 CPUMIPSState *env) 170 { 171 int32_t tempI; 172 173 tempI = a + b; 174 175 if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x80000000)) { 176 if (a > 0) { 177 tempI = 0x7FFFFFFF; 178 } else { 179 tempI = 0x80000000; 180 } 181 set_DSPControl_overflow_flag(1, 20, env); 182 } 183 184 return tempI; 185 } 186 187 static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env) 188 { 189 uint16_t temp; 190 191 temp = (uint16_t)a + (uint16_t)b; 192 193 if (temp & 0x0100) { 194 set_DSPControl_overflow_flag(1, 20, env); 195 } 196 197 return temp & 0xFF; 198 } 199 200 static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b, 201 CPUMIPSState *env) 202 { 203 uint32_t temp; 204 205 temp = (uint32_t)a + (uint32_t)b; 206 207 if (temp & 0x00010000) { 208 set_DSPControl_overflow_flag(1, 20, env); 209 } 210 211 return temp & 0xFFFF; 212 } 213 214 static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b, 215 CPUMIPSState *env) 216 { 217 uint8_t result; 218 uint16_t temp; 219 220 temp = (uint16_t)a + (uint16_t)b; 221 result = temp & 0xFF; 222 223 if (0x0100 & temp) { 224 result = 0xFF; 225 set_DSPControl_overflow_flag(1, 20, env); 226 } 227 228 return result; 229 } 230 231 static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b, 232 CPUMIPSState *env) 233 { 234 uint16_t result; 235 uint32_t temp; 236 237 temp = (uint32_t)a + (uint32_t)b; 238 result = temp & 0xFFFF; 239 240 if (0x00010000 & temp) { 241 result = 0xFFFF; 242 set_DSPControl_overflow_flag(1, 20, env); 243 } 244 245 return result; 246 } 247 248 static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a, 249 CPUMIPSState *env) 250 { 251 int64_t temp; 252 int32_t temp32, temp31, result; 253 int64_t temp_sum; 254 255 #ifndef TARGET_MIPS64 256 temp = ((uint64_t)env->active_tc.HI[acc] << 32) | 257 (uint64_t)env->active_tc.LO[acc]; 258 #else 259 temp = (uint64_t)env->active_tc.LO[acc]; 260 #endif 261 262 temp_sum = (int64_t)a + temp; 263 264 temp32 = (temp_sum >> 32) & 0x01; 265 temp31 = (temp_sum >> 31) & 0x01; 266 result = temp_sum & 0xFFFFFFFF; 267 268 if (temp32 != temp31) { 269 if (temp32 == 0) { 270 result = 0x7FFFFFFF; 271 } else { 272 result = 0x80000000; 273 } 274 set_DSPControl_overflow_flag(1, 16 + acc, env); 275 } 276 277 return result; 278 } 279 280 #ifdef TARGET_MIPS64 281 /* a[0] is LO, a[1] is HI. */ 282 static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret, 283 int32_t ac, 284 int64_t *a, 285 CPUMIPSState *env) 286 { 287 bool temp64; 288 289 ret[0] = env->active_tc.LO[ac] + a[0]; 290 ret[1] = env->active_tc.HI[ac] + a[1]; 291 292 if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) && 293 ((uint64_t)ret[0] < (uint64_t)a[0])) { 294 ret[1] += 1; 295 } 296 temp64 = ret[1] & 1; 297 if (temp64 != ((ret[0] >> 63) & 0x01)) { 298 if (temp64) { 299 ret[0] = (0x01ull << 63); 300 ret[1] = ~0ull; 301 } else { 302 ret[0] = (0x01ull << 63) - 1; 303 ret[1] = 0x00; 304 } 305 set_DSPControl_overflow_flag(1, 16 + ac, env); 306 } 307 } 308 309 static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret, 310 int32_t ac, 311 int64_t *a, 312 CPUMIPSState *env) 313 { 314 bool temp64; 315 316 ret[0] = env->active_tc.LO[ac] - a[0]; 317 ret[1] = env->active_tc.HI[ac] - a[1]; 318 319 if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) { 320 ret[1] -= 1; 321 } 322 temp64 = ret[1] & 1; 323 if (temp64 != ((ret[0] >> 63) & 0x01)) { 324 if (temp64) { 325 ret[0] = (0x01ull << 63); 326 ret[1] = ~0ull; 327 } else { 328 ret[0] = (0x01ull << 63) - 1; 329 ret[1] = 0x00; 330 } 331 set_DSPControl_overflow_flag(1, 16 + ac, env); 332 } 333 } 334 #endif 335 336 static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b, 337 CPUMIPSState *env) 338 { 339 int32_t temp; 340 341 temp = (int32_t)a * (int32_t)b; 342 343 if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) { 344 set_DSPControl_overflow_flag(1, 21, env); 345 } 346 temp &= 0x0000FFFF; 347 348 return temp; 349 } 350 351 static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b) 352 { 353 return a * b; 354 } 355 356 #ifdef TARGET_MIPS64 357 static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b) 358 { 359 return a * b; 360 } 361 #endif 362 363 static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b, 364 CPUMIPSState *env) 365 { 366 int32_t temp; 367 368 temp = (int32_t)a * (int32_t)b; 369 370 if (temp > (int)0x7FFF) { 371 temp = 0x00007FFF; 372 set_DSPControl_overflow_flag(1, 21, env); 373 } else if (temp < (int)0xffff8000) { 374 temp = 0xFFFF8000; 375 set_DSPControl_overflow_flag(1, 21, env); 376 } 377 temp &= 0x0000FFFF; 378 379 return temp; 380 } 381 382 static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b, 383 CPUMIPSState *env) 384 { 385 int32_t temp; 386 387 if ((a == 0x8000) && (b == 0x8000)) { 388 temp = 0x7FFFFFFF; 389 set_DSPControl_overflow_flag(1, 21, env); 390 } else { 391 temp = ((int16_t)a * (int16_t)b) << 1; 392 } 393 394 return temp; 395 } 396 397 /* right shift */ 398 static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov) 399 { 400 return a >> mov; 401 } 402 403 static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov) 404 { 405 return a >> mov; 406 } 407 408 static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov) 409 { 410 return a >> mov; 411 } 412 413 static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov) 414 { 415 return a >> mov; 416 } 417 418 #ifdef TARGET_MIPS64 419 static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov) 420 { 421 return a >> mov; 422 } 423 #endif 424 425 static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b) 426 { 427 int32_t temp; 428 429 temp = (int32_t)a + (int32_t)b; 430 431 return (temp >> 1) & 0xFFFF; 432 } 433 434 /* round right shift */ 435 static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b) 436 { 437 int32_t temp; 438 439 temp = (int32_t)a + (int32_t)b; 440 temp += 1; 441 442 return (temp >> 1) & 0xFFFF; 443 } 444 445 static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b) 446 { 447 int64_t temp; 448 449 temp = (int64_t)a + (int64_t)b; 450 451 return (temp >> 1) & 0xFFFFFFFF; 452 } 453 454 static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b) 455 { 456 int64_t temp; 457 458 temp = (int64_t)a + (int64_t)b; 459 temp += 1; 460 461 return (temp >> 1) & 0xFFFFFFFF; 462 } 463 464 static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b) 465 { 466 uint16_t temp; 467 468 temp = (uint16_t)a + (uint16_t)b; 469 470 return (temp >> 1) & 0x00FF; 471 } 472 473 static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b) 474 { 475 uint16_t temp; 476 477 temp = (uint16_t)a + (uint16_t)b + 1; 478 479 return (temp >> 1) & 0x00FF; 480 } 481 482 #ifdef TARGET_MIPS64 483 static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b) 484 { 485 uint16_t temp; 486 487 temp = (uint16_t)a - (uint16_t)b; 488 489 return (temp >> 1) & 0x00FF; 490 } 491 492 static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b) 493 { 494 uint16_t temp; 495 496 temp = (uint16_t)a - (uint16_t)b + 1; 497 498 return (temp >> 1) & 0x00FF; 499 } 500 #endif 501 502 /* 128 bits long. p[0] is LO, p[1] is HI. */ 503 static inline void mipsdsp_rndrashift_short_acc(int64_t *p, 504 int32_t ac, 505 int32_t shift, 506 CPUMIPSState *env) 507 { 508 int64_t acc; 509 510 acc = ((int64_t)env->active_tc.HI[ac] << 32) | 511 ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); 512 p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1)); 513 p[1] = (acc >> 63) & 0x01; 514 } 515 516 #ifdef TARGET_MIPS64 517 /* 128 bits long. p[0] is LO, p[1] is HI */ 518 static inline void mipsdsp_rashift_acc(uint64_t *p, 519 uint32_t ac, 520 uint32_t shift, 521 CPUMIPSState *env) 522 { 523 uint64_t tempB, tempA; 524 525 tempB = env->active_tc.HI[ac]; 526 tempA = env->active_tc.LO[ac]; 527 shift = shift & 0x1F; 528 529 if (shift == 0) { 530 p[1] = tempB; 531 p[0] = tempA; 532 } else { 533 p[0] = (tempB << (64 - shift)) | (tempA >> shift); 534 p[1] = (int64_t)tempB >> shift; 535 } 536 } 537 538 /* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/ 539 static inline void mipsdsp_rndrashift_acc(uint64_t *p, 540 uint32_t ac, 541 uint32_t shift, 542 CPUMIPSState *env) 543 { 544 int64_t tempB, tempA; 545 546 tempB = env->active_tc.HI[ac]; 547 tempA = env->active_tc.LO[ac]; 548 shift = shift & 0x3F; 549 550 if (shift == 0) { 551 p[2] = tempB >> 63; 552 p[1] = (tempB << 1) | (tempA >> 63); 553 p[0] = tempA << 1; 554 } else { 555 p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1)); 556 p[1] = (int64_t)tempB >> (shift - 1); 557 if (tempB >= 0) { 558 p[2] = 0x0; 559 } else { 560 p[2] = ~0ull; 561 } 562 } 563 } 564 #endif 565 566 static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b, 567 CPUMIPSState *env) 568 { 569 int32_t temp; 570 571 if ((a == 0x8000) && (b == 0x8000)) { 572 temp = 0x7FFFFFFF; 573 set_DSPControl_overflow_flag(1, 16 + ac, env); 574 } else { 575 temp = ((int16_t)a * (int16_t)b) << 1; 576 } 577 578 return temp; 579 } 580 581 static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b, 582 CPUMIPSState *env) 583 { 584 uint64_t temp; 585 586 if ((a == 0x80000000) && (b == 0x80000000)) { 587 temp = (0x01ull << 63) - 1; 588 set_DSPControl_overflow_flag(1, 16 + ac, env); 589 } else { 590 temp = ((int64_t)(int32_t)a * (int32_t)b) << 1; 591 } 592 593 return temp; 594 } 595 596 static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b) 597 { 598 return (uint16_t)a * (uint16_t)b; 599 } 600 601 static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b, 602 CPUMIPSState *env) 603 { 604 uint32_t tempI; 605 606 tempI = (uint32_t)a * (uint32_t)b; 607 if (tempI > 0x0000FFFF) { 608 tempI = 0x0000FFFF; 609 set_DSPControl_overflow_flag(1, 21, env); 610 } 611 612 return tempI & 0x0000FFFF; 613 } 614 615 #ifdef TARGET_MIPS64 616 static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b) 617 { 618 return (uint64_t)a * (uint64_t)b; 619 } 620 #endif 621 622 static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b, 623 CPUMIPSState *env) 624 { 625 uint32_t temp; 626 627 if ((a == 0x8000) && (b == 0x8000)) { 628 temp = 0x7FFF0000; 629 set_DSPControl_overflow_flag(1, 21, env); 630 } else { 631 temp = ((int16_t)a * (int16_t)b) << 1; 632 temp = temp + 0x00008000; 633 } 634 635 return (temp & 0xFFFF0000) >> 16; 636 } 637 638 static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b, 639 CPUMIPSState *env) 640 { 641 int32_t temp; 642 643 if ((a == 0x8000) && (b == 0x8000)) { 644 temp = 0x7FFF0000; 645 set_DSPControl_overflow_flag(1, 21, env); 646 } else { 647 temp = (int16_t)a * (int16_t)b; 648 temp = temp << 1; 649 } 650 651 return (temp >> 16) & 0x0000FFFF; 652 } 653 654 static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a, 655 CPUMIPSState *env) 656 { 657 uint16_t temp; 658 659 660 /* 661 * The value 0x00008000 will be added to the input Q31 value, and the code 662 * needs to check if the addition causes an overflow. Since a positive value 663 * is added, overflow can happen in one direction only. 664 */ 665 if (a > 0x7FFF7FFF) { 666 temp = 0x7FFF; 667 set_DSPControl_overflow_flag(1, 22, env); 668 } else { 669 temp = ((a + 0x8000) >> 16) & 0xFFFF; 670 } 671 672 return temp; 673 } 674 675 static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a, 676 CPUMIPSState *env) 677 { 678 uint16_t mag; 679 uint32_t sign; 680 681 sign = (a >> 15) & 0x01; 682 mag = a & 0x7FFF; 683 684 if (sign == 0) { 685 if (mag > 0x7F80) { 686 set_DSPControl_overflow_flag(1, 22, env); 687 return 0xFF; 688 } else { 689 return (mag >> 7) & 0xFFFF; 690 } 691 } else { 692 set_DSPControl_overflow_flag(1, 22, env); 693 return 0x00; 694 } 695 } 696 697 static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env) 698 { 699 uint8_t discard; 700 701 if (s != 0) { 702 discard = a >> (8 - s); 703 704 if (discard != 0x00) { 705 set_DSPControl_overflow_flag(1, 22, env); 706 } 707 } 708 return a << s; 709 } 710 711 static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s, 712 CPUMIPSState *env) 713 { 714 uint16_t discard; 715 716 if (s != 0) { 717 discard = (int16_t)a >> (15 - s); 718 719 if ((discard != 0x0000) && (discard != 0xFFFF)) { 720 set_DSPControl_overflow_flag(1, 22, env); 721 } 722 } 723 return a << s; 724 } 725 726 #ifdef TARGET_MIPS64 727 static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s, 728 CPUMIPSState *env) 729 { 730 uint32_t discard; 731 732 if (s == 0) { 733 return a; 734 } else { 735 discard = (int32_t)a >> (31 - (s - 1)); 736 737 if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) { 738 set_DSPControl_overflow_flag(1, 22, env); 739 } 740 return a << s; 741 } 742 } 743 #endif 744 745 static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s, 746 CPUMIPSState *env) 747 { 748 uint8_t sign; 749 uint16_t discard; 750 751 if (s == 0) { 752 return a; 753 } else { 754 sign = (a >> 15) & 0x01; 755 if (sign != 0) { 756 discard = (((0x01 << (16 - s)) - 1) << s) | 757 ((a >> (14 - (s - 1))) & ((0x01 << s) - 1)); 758 } else { 759 discard = a >> (14 - (s - 1)); 760 } 761 762 if ((discard != 0x0000) && (discard != 0xFFFF)) { 763 set_DSPControl_overflow_flag(1, 22, env); 764 return (sign == 0) ? 0x7FFF : 0x8000; 765 } else { 766 return a << s; 767 } 768 } 769 } 770 771 static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s, 772 CPUMIPSState *env) 773 { 774 uint8_t sign; 775 uint32_t discard; 776 777 if (s == 0) { 778 return a; 779 } else { 780 sign = (a >> 31) & 0x01; 781 if (sign != 0) { 782 discard = (((0x01 << (32 - s)) - 1) << s) | 783 ((a >> (30 - (s - 1))) & ((0x01 << s) - 1)); 784 } else { 785 discard = a >> (30 - (s - 1)); 786 } 787 788 if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) { 789 set_DSPControl_overflow_flag(1, 22, env); 790 return (sign == 0) ? 0x7FFFFFFF : 0x80000000; 791 } else { 792 return a << s; 793 } 794 } 795 } 796 797 static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s) 798 { 799 uint32_t temp; 800 801 if (s == 0) { 802 temp = (uint32_t)a << 1; 803 } else { 804 temp = (int32_t)(int8_t)a >> (s - 1); 805 } 806 807 return (temp + 1) >> 1; 808 } 809 810 static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s) 811 { 812 uint32_t temp; 813 814 if (s == 0) { 815 temp = (uint32_t)a << 1; 816 } else { 817 temp = (int32_t)(int16_t)a >> (s - 1); 818 } 819 820 return (temp + 1) >> 1; 821 } 822 823 static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s) 824 { 825 int64_t temp; 826 827 if (s == 0) { 828 temp = (uint64_t)a << 1; 829 } else { 830 temp = (int64_t)(int32_t)a >> (s - 1); 831 } 832 temp += 1; 833 834 return (temp >> 1) & 0xFFFFFFFFull; 835 } 836 837 static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env) 838 { 839 int16_t temp; 840 841 temp = a - b; 842 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) { 843 set_DSPControl_overflow_flag(1, 20, env); 844 } 845 846 return temp; 847 } 848 849 static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b, 850 CPUMIPSState *env) 851 { 852 int16_t temp; 853 854 temp = a - b; 855 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) { 856 if (a >= 0) { 857 temp = 0x7FFF; 858 } else { 859 temp = 0x8000; 860 } 861 set_DSPControl_overflow_flag(1, 20, env); 862 } 863 864 return temp; 865 } 866 867 static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b, 868 CPUMIPSState *env) 869 { 870 int32_t temp; 871 872 temp = a - b; 873 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) { 874 if (a >= 0) { 875 temp = 0x7FFFFFFF; 876 } else { 877 temp = 0x80000000; 878 } 879 set_DSPControl_overflow_flag(1, 20, env); 880 } 881 882 return temp & 0xFFFFFFFFull; 883 } 884 885 static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b) 886 { 887 int32_t temp; 888 889 temp = (int32_t)a - (int32_t)b; 890 891 return (temp >> 1) & 0x0000FFFF; 892 } 893 894 static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b) 895 { 896 int32_t temp; 897 898 temp = (int32_t)a - (int32_t)b; 899 temp += 1; 900 901 return (temp >> 1) & 0x0000FFFF; 902 } 903 904 static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b) 905 { 906 int64_t temp; 907 908 temp = (int64_t)a - (int64_t)b; 909 910 return (temp >> 1) & 0xFFFFFFFFull; 911 } 912 913 static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b) 914 { 915 int64_t temp; 916 917 temp = (int64_t)a - (int64_t)b; 918 temp += 1; 919 920 return (temp >> 1) & 0xFFFFFFFFull; 921 } 922 923 static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b, 924 CPUMIPSState *env) 925 { 926 uint8_t temp16; 927 uint32_t temp; 928 929 temp = (uint32_t)a - (uint32_t)b; 930 temp16 = (temp >> 16) & 0x01; 931 if (temp16 == 1) { 932 set_DSPControl_overflow_flag(1, 20, env); 933 } 934 return temp & 0x0000FFFF; 935 } 936 937 static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b, 938 CPUMIPSState *env) 939 { 940 uint8_t temp16; 941 uint32_t temp; 942 943 temp = (uint32_t)a - (uint32_t)b; 944 temp16 = (temp >> 16) & 0x01; 945 946 if (temp16 == 1) { 947 temp = 0x0000; 948 set_DSPControl_overflow_flag(1, 20, env); 949 } 950 951 return temp & 0x0000FFFF; 952 } 953 954 static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env) 955 { 956 uint8_t temp8; 957 uint16_t temp; 958 959 temp = (uint16_t)a - (uint16_t)b; 960 temp8 = (temp >> 8) & 0x01; 961 if (temp8 == 1) { 962 set_DSPControl_overflow_flag(1, 20, env); 963 } 964 965 return temp & 0x00FF; 966 } 967 968 static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env) 969 { 970 uint8_t temp8; 971 uint16_t temp; 972 973 temp = (uint16_t)a - (uint16_t)b; 974 temp8 = (temp >> 8) & 0x01; 975 if (temp8 == 1) { 976 temp = 0x00; 977 set_DSPControl_overflow_flag(1, 20, env); 978 } 979 980 return temp & 0x00FF; 981 } 982 983 #ifdef TARGET_MIPS64 984 static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env) 985 { 986 int32_t temp; 987 988 temp = a - b; 989 if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) { 990 set_DSPControl_overflow_flag(1, 20, env); 991 } 992 993 return temp; 994 } 995 996 static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env) 997 { 998 int32_t temp; 999 1000 temp = a + b; 1001 1002 if (MIPSDSP_OVERFLOW_ADD(a, b, temp, 0x80000000)) { 1003 set_DSPControl_overflow_flag(1, 20, env); 1004 } 1005 1006 return temp; 1007 } 1008 #endif 1009 1010 static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b) 1011 { 1012 return a == b; 1013 } 1014 1015 static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b) 1016 { 1017 return a <= b; 1018 } 1019 1020 static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b) 1021 { 1022 return a < b; 1023 } 1024 1025 static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b) 1026 { 1027 return a == b; 1028 } 1029 1030 static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b) 1031 { 1032 return a <= b; 1033 } 1034 1035 static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b) 1036 { 1037 return a < b; 1038 } 1039 /*** MIPS DSP internal functions end ***/ 1040 1041 #define MIPSDSP_LHI 0xFFFFFFFF00000000ull 1042 #define MIPSDSP_LLO 0x00000000FFFFFFFFull 1043 #define MIPSDSP_HI 0xFFFF0000 1044 #define MIPSDSP_LO 0x0000FFFF 1045 #define MIPSDSP_Q3 0xFF000000 1046 #define MIPSDSP_Q2 0x00FF0000 1047 #define MIPSDSP_Q1 0x0000FF00 1048 #define MIPSDSP_Q0 0x000000FF 1049 1050 #define MIPSDSP_SPLIT32_8(num, a, b, c, d) \ 1051 do { \ 1052 a = ((num) >> 24) & MIPSDSP_Q0; \ 1053 b = ((num) >> 16) & MIPSDSP_Q0; \ 1054 c = ((num) >> 8) & MIPSDSP_Q0; \ 1055 d = (num) & MIPSDSP_Q0; \ 1056 } while (0) 1057 1058 #define MIPSDSP_SPLIT32_16(num, a, b) \ 1059 do { \ 1060 a = ((num) >> 16) & MIPSDSP_LO; \ 1061 b = (num) & MIPSDSP_LO; \ 1062 } while (0) 1063 1064 #define MIPSDSP_RETURN32_8(a, b, c, d) ((target_long)(int32_t) \ 1065 (((uint32_t)(a) << 24) | \ 1066 ((uint32_t)(b) << 16) | \ 1067 ((uint32_t)(c) << 8) | \ 1068 ((uint32_t)(d) & 0xFF))) 1069 #define MIPSDSP_RETURN32_16(a, b) ((target_long)(int32_t) \ 1070 (((uint32_t)(a) << 16) | \ 1071 ((uint32_t)(b) & 0xFFFF))) 1072 1073 #ifdef TARGET_MIPS64 1074 #define MIPSDSP_SPLIT64_16(num, a, b, c, d) \ 1075 do { \ 1076 a = ((num) >> 48) & MIPSDSP_LO; \ 1077 b = ((num) >> 32) & MIPSDSP_LO; \ 1078 c = ((num) >> 16) & MIPSDSP_LO; \ 1079 d = (num) & MIPSDSP_LO; \ 1080 } while (0) 1081 1082 #define MIPSDSP_SPLIT64_32(num, a, b) \ 1083 do { \ 1084 a = ((num) >> 32) & MIPSDSP_LLO; \ 1085 b = (num) & MIPSDSP_LLO; \ 1086 } while (0) 1087 1088 #define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)(a) << 48) | \ 1089 ((uint64_t)(b) << 32) | \ 1090 ((uint64_t)(c) << 16) | \ 1091 (uint64_t)(d)) 1092 #define MIPSDSP_RETURN64_32(a, b) (((uint64_t)(a) << 32) | (uint64_t)(b)) 1093 #endif 1094 1095 /** DSP Arithmetic Sub-class insns **/ 1096 #define MIPSDSP32_UNOP_ENV(name, func, element) \ 1097 target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \ 1098 { \ 1099 DSP32Value dt; \ 1100 unsigned int i; \ 1101 \ 1102 dt.sw[0] = rt; \ 1103 \ 1104 for (i = 0; i < ARRAY_SIZE(dt.element); i++) { \ 1105 dt.element[i] = mipsdsp_##func(dt.element[i], env); \ 1106 } \ 1107 \ 1108 return (target_long)dt.sw[0]; \ 1109 } 1110 MIPSDSP32_UNOP_ENV(absq_s_ph, sat_abs16, sh) 1111 MIPSDSP32_UNOP_ENV(absq_s_qb, sat_abs8, sb) 1112 MIPSDSP32_UNOP_ENV(absq_s_w, sat_abs32, sw) 1113 #undef MIPSDSP32_UNOP_ENV 1114 1115 #if defined(TARGET_MIPS64) 1116 #define MIPSDSP64_UNOP_ENV(name, func, element) \ 1117 target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \ 1118 { \ 1119 DSP64Value dt; \ 1120 unsigned int i; \ 1121 \ 1122 dt.sl[0] = rt; \ 1123 \ 1124 for (i = 0; i < ARRAY_SIZE(dt.element); i++) { \ 1125 dt.element[i] = mipsdsp_##func(dt.element[i], env); \ 1126 } \ 1127 \ 1128 return dt.sl[0]; \ 1129 } 1130 MIPSDSP64_UNOP_ENV(absq_s_ob, sat_abs8, sb) 1131 MIPSDSP64_UNOP_ENV(absq_s_qh, sat_abs16, sh) 1132 MIPSDSP64_UNOP_ENV(absq_s_pw, sat_abs32, sw) 1133 #undef MIPSDSP64_UNOP_ENV 1134 #endif 1135 1136 #define MIPSDSP32_BINOP(name, func, element) \ 1137 target_ulong helper_##name(target_ulong rs, target_ulong rt) \ 1138 { \ 1139 DSP32Value ds, dt; \ 1140 unsigned int i; \ 1141 \ 1142 ds.sw[0] = rs; \ 1143 dt.sw[0] = rt; \ 1144 \ 1145 for (i = 0; i < ARRAY_SIZE(ds.element); i++) { \ 1146 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \ 1147 } \ 1148 \ 1149 return (target_long)ds.sw[0]; \ 1150 } 1151 MIPSDSP32_BINOP(addqh_ph, rshift1_add_q16, sh); 1152 MIPSDSP32_BINOP(addqh_r_ph, rrshift1_add_q16, sh); 1153 MIPSDSP32_BINOP(addqh_r_w, rrshift1_add_q32, sw); 1154 MIPSDSP32_BINOP(addqh_w, rshift1_add_q32, sw); 1155 MIPSDSP32_BINOP(adduh_qb, rshift1_add_u8, ub); 1156 MIPSDSP32_BINOP(adduh_r_qb, rrshift1_add_u8, ub); 1157 MIPSDSP32_BINOP(subqh_ph, rshift1_sub_q16, sh); 1158 MIPSDSP32_BINOP(subqh_r_ph, rrshift1_sub_q16, sh); 1159 MIPSDSP32_BINOP(subqh_r_w, rrshift1_sub_q32, sw); 1160 MIPSDSP32_BINOP(subqh_w, rshift1_sub_q32, sw); 1161 #undef MIPSDSP32_BINOP 1162 1163 #define MIPSDSP32_BINOP_ENV(name, func, element) \ 1164 target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 1165 CPUMIPSState *env) \ 1166 { \ 1167 DSP32Value ds, dt; \ 1168 unsigned int i; \ 1169 \ 1170 ds.sw[0] = rs; \ 1171 dt.sw[0] = rt; \ 1172 \ 1173 for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) { \ 1174 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \ 1175 } \ 1176 \ 1177 return (target_long)ds.sw[0]; \ 1178 } 1179 MIPSDSP32_BINOP_ENV(addq_ph, add_i16, sh) 1180 MIPSDSP32_BINOP_ENV(addq_s_ph, sat_add_i16, sh) 1181 MIPSDSP32_BINOP_ENV(addq_s_w, sat_add_i32, sw); 1182 MIPSDSP32_BINOP_ENV(addu_ph, add_u16, sh) 1183 MIPSDSP32_BINOP_ENV(addu_qb, add_u8, ub); 1184 MIPSDSP32_BINOP_ENV(addu_s_ph, sat_add_u16, sh) 1185 MIPSDSP32_BINOP_ENV(addu_s_qb, sat_add_u8, ub); 1186 MIPSDSP32_BINOP_ENV(subq_ph, sub_i16, sh); 1187 MIPSDSP32_BINOP_ENV(subq_s_ph, sat16_sub, sh); 1188 MIPSDSP32_BINOP_ENV(subq_s_w, sat32_sub, sw); 1189 MIPSDSP32_BINOP_ENV(subu_ph, sub_u16_u16, sh); 1190 MIPSDSP32_BINOP_ENV(subu_qb, sub_u8, ub); 1191 MIPSDSP32_BINOP_ENV(subu_s_ph, satu16_sub_u16_u16, sh); 1192 MIPSDSP32_BINOP_ENV(subu_s_qb, satu8_sub, ub); 1193 #undef MIPSDSP32_BINOP_ENV 1194 1195 #ifdef TARGET_MIPS64 1196 #define MIPSDSP64_BINOP(name, func, element) \ 1197 target_ulong helper_##name(target_ulong rs, target_ulong rt) \ 1198 { \ 1199 DSP64Value ds, dt; \ 1200 unsigned int i; \ 1201 \ 1202 ds.sl[0] = rs; \ 1203 dt.sl[0] = rt; \ 1204 \ 1205 for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) { \ 1206 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \ 1207 } \ 1208 \ 1209 return ds.sl[0]; \ 1210 } 1211 MIPSDSP64_BINOP(adduh_ob, rshift1_add_u8, ub); 1212 MIPSDSP64_BINOP(adduh_r_ob, rrshift1_add_u8, ub); 1213 MIPSDSP64_BINOP(subuh_ob, rshift1_sub_u8, ub); 1214 MIPSDSP64_BINOP(subuh_r_ob, rrshift1_sub_u8, ub); 1215 #undef MIPSDSP64_BINOP 1216 1217 #define MIPSDSP64_BINOP_ENV(name, func, element) \ 1218 target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 1219 CPUMIPSState *env) \ 1220 { \ 1221 DSP64Value ds, dt; \ 1222 unsigned int i; \ 1223 \ 1224 ds.sl[0] = rs; \ 1225 dt.sl[0] = rt; \ 1226 \ 1227 for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) { \ 1228 ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \ 1229 } \ 1230 \ 1231 return ds.sl[0]; \ 1232 } 1233 MIPSDSP64_BINOP_ENV(addq_pw, add_i32, sw); 1234 MIPSDSP64_BINOP_ENV(addq_qh, add_i16, sh); 1235 MIPSDSP64_BINOP_ENV(addq_s_pw, sat_add_i32, sw); 1236 MIPSDSP64_BINOP_ENV(addq_s_qh, sat_add_i16, sh); 1237 MIPSDSP64_BINOP_ENV(addu_ob, add_u8, uh); 1238 MIPSDSP64_BINOP_ENV(addu_qh, add_u16, uh); 1239 MIPSDSP64_BINOP_ENV(addu_s_ob, sat_add_u8, uh); 1240 MIPSDSP64_BINOP_ENV(addu_s_qh, sat_add_u16, uh); 1241 MIPSDSP64_BINOP_ENV(subq_pw, sub32, sw); 1242 MIPSDSP64_BINOP_ENV(subq_qh, sub_i16, sh); 1243 MIPSDSP64_BINOP_ENV(subq_s_pw, sat32_sub, sw); 1244 MIPSDSP64_BINOP_ENV(subq_s_qh, sat16_sub, sh); 1245 MIPSDSP64_BINOP_ENV(subu_ob, sub_u8, uh); 1246 MIPSDSP64_BINOP_ENV(subu_qh, sub_u16_u16, uh); 1247 MIPSDSP64_BINOP_ENV(subu_s_ob, satu8_sub, uh); 1248 MIPSDSP64_BINOP_ENV(subu_s_qh, satu16_sub_u16_u16, uh); 1249 #undef MIPSDSP64_BINOP_ENV 1250 1251 #endif 1252 1253 #define SUBUH_QB(name, var) \ 1254 target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \ 1255 { \ 1256 uint8_t rs3, rs2, rs1, rs0; \ 1257 uint8_t rt3, rt2, rt1, rt0; \ 1258 uint8_t tempD, tempC, tempB, tempA; \ 1259 \ 1260 MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \ 1261 MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 1262 \ 1263 tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1; \ 1264 tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1; \ 1265 tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1; \ 1266 tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1; \ 1267 \ 1268 return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \ 1269 ((uint32_t)tempB << 8) | ((uint32_t)tempA); \ 1270 } 1271 1272 SUBUH_QB(subuh, 0); 1273 SUBUH_QB(subuh_r, 1); 1274 1275 #undef SUBUH_QB 1276 1277 target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env) 1278 { 1279 uint64_t temp, tempRs, tempRt; 1280 bool flag; 1281 1282 tempRs = (uint64_t)rs & MIPSDSP_LLO; 1283 tempRt = (uint64_t)rt & MIPSDSP_LLO; 1284 1285 temp = tempRs + tempRt; 1286 flag = (temp & 0x0100000000ull) >> 32; 1287 set_DSPControl_carryflag(flag, env); 1288 1289 return (target_long)(int32_t)(temp & MIPSDSP_LLO); 1290 } 1291 1292 target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env) 1293 { 1294 uint32_t rd; 1295 int32_t temp32, temp31; 1296 int64_t tempL; 1297 1298 tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt + 1299 get_DSPControl_carryflag(env); 1300 temp31 = (tempL >> 31) & 0x01; 1301 temp32 = (tempL >> 32) & 0x01; 1302 1303 if (temp31 != temp32) { 1304 set_DSPControl_overflow_flag(1, 20, env); 1305 } 1306 1307 rd = tempL & MIPSDSP_LLO; 1308 1309 return (target_long)(int32_t)rd; 1310 } 1311 1312 target_ulong helper_modsub(target_ulong rs, target_ulong rt) 1313 { 1314 int32_t decr; 1315 uint16_t lastindex; 1316 target_ulong rd; 1317 1318 decr = rt & MIPSDSP_Q0; 1319 lastindex = (rt >> 8) & MIPSDSP_LO; 1320 1321 if ((rs & MIPSDSP_LLO) == 0x00000000) { 1322 rd = (target_ulong)lastindex; 1323 } else { 1324 rd = rs - decr; 1325 } 1326 1327 return rd; 1328 } 1329 1330 target_ulong helper_raddu_w_qb(target_ulong rs) 1331 { 1332 target_ulong ret = 0; 1333 DSP32Value ds; 1334 unsigned int i; 1335 1336 ds.uw[0] = rs; 1337 for (i = 0; i < 4; i++) { 1338 ret += ds.ub[i]; 1339 } 1340 return ret; 1341 } 1342 1343 #if defined(TARGET_MIPS64) 1344 target_ulong helper_raddu_l_ob(target_ulong rs) 1345 { 1346 target_ulong ret = 0; 1347 DSP64Value ds; 1348 unsigned int i; 1349 1350 ds.ul[0] = rs; 1351 for (i = 0; i < 8; i++) { 1352 ret += ds.ub[i]; 1353 } 1354 return ret; 1355 } 1356 #endif 1357 1358 #define PRECR_QB_PH(name, a, b)\ 1359 target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \ 1360 { \ 1361 uint8_t tempD, tempC, tempB, tempA; \ 1362 \ 1363 tempD = (rs >> a) & MIPSDSP_Q0; \ 1364 tempC = (rs >> b) & MIPSDSP_Q0; \ 1365 tempB = (rt >> a) & MIPSDSP_Q0; \ 1366 tempA = (rt >> b) & MIPSDSP_Q0; \ 1367 \ 1368 return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); \ 1369 } 1370 1371 PRECR_QB_PH(precr, 16, 0); 1372 PRECR_QB_PH(precrq, 24, 8); 1373 1374 #undef PRECR_QB_OH 1375 1376 target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs, 1377 target_ulong rt) 1378 { 1379 uint16_t tempB, tempA; 1380 1381 tempB = ((int32_t)rt >> sa) & MIPSDSP_LO; 1382 tempA = ((int32_t)rs >> sa) & MIPSDSP_LO; 1383 1384 return MIPSDSP_RETURN32_16(tempB, tempA); 1385 } 1386 1387 target_ulong helper_precr_sra_r_ph_w(uint32_t sa, 1388 target_ulong rs, target_ulong rt) 1389 { 1390 uint64_t tempB, tempA; 1391 1392 /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */ 1393 if (sa == 0) { 1394 tempB = (rt & MIPSDSP_LO) << 1; 1395 tempA = (rs & MIPSDSP_LO) << 1; 1396 } else { 1397 tempB = ((int32_t)rt >> (sa - 1)) + 1; 1398 tempA = ((int32_t)rs >> (sa - 1)) + 1; 1399 } 1400 rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO); 1401 1402 return (target_long)(int32_t)rt; 1403 } 1404 1405 target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt) 1406 { 1407 uint16_t tempB, tempA; 1408 1409 tempB = (rs & MIPSDSP_HI) >> 16; 1410 tempA = (rt & MIPSDSP_HI) >> 16; 1411 1412 return MIPSDSP_RETURN32_16(tempB, tempA); 1413 } 1414 1415 target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt, 1416 CPUMIPSState *env) 1417 { 1418 uint16_t tempB, tempA; 1419 1420 tempB = mipsdsp_trunc16_sat16_round(rs, env); 1421 tempA = mipsdsp_trunc16_sat16_round(rt, env); 1422 1423 return MIPSDSP_RETURN32_16(tempB, tempA); 1424 } 1425 1426 #if defined(TARGET_MIPS64) 1427 target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt) 1428 { 1429 uint8_t rs6, rs4, rs2, rs0; 1430 uint8_t rt6, rt4, rt2, rt0; 1431 uint64_t temp; 1432 1433 rs6 = (rs >> 48) & MIPSDSP_Q0; 1434 rs4 = (rs >> 32) & MIPSDSP_Q0; 1435 rs2 = (rs >> 16) & MIPSDSP_Q0; 1436 rs0 = rs & MIPSDSP_Q0; 1437 rt6 = (rt >> 48) & MIPSDSP_Q0; 1438 rt4 = (rt >> 32) & MIPSDSP_Q0; 1439 rt2 = (rt >> 16) & MIPSDSP_Q0; 1440 rt0 = rt & MIPSDSP_Q0; 1441 1442 temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) | 1443 ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) | 1444 ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) | 1445 ((uint64_t)rt2 << 8) | (uint64_t)rt0; 1446 1447 return temp; 1448 } 1449 1450 1451 /* 1452 * In case sa == 0, use rt2, rt0, rs2, rs0. 1453 * In case sa != 0, use rt3, rt1, rs3, rs1. 1454 */ 1455 #define PRECR_QH_PW(name, var) \ 1456 target_ulong helper_precr_##name##_qh_pw(target_ulong rs, \ 1457 target_ulong rt, \ 1458 uint32_t sa) \ 1459 { \ 1460 uint16_t rs3, rs2, rs1, rs0; \ 1461 uint16_t rt3, rt2, rt1, rt0; \ 1462 uint16_t tempD, tempC, tempB, tempA; \ 1463 \ 1464 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ 1465 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 1466 \ 1467 if (sa == 0) { \ 1468 tempD = rt2 << var; \ 1469 tempC = rt0 << var; \ 1470 tempB = rs2 << var; \ 1471 tempA = rs0 << var; \ 1472 } else { \ 1473 tempD = (((int16_t)rt3 >> sa) + var) >> var; \ 1474 tempC = (((int16_t)rt1 >> sa) + var) >> var; \ 1475 tempB = (((int16_t)rs3 >> sa) + var) >> var; \ 1476 tempA = (((int16_t)rs1 >> sa) + var) >> var; \ 1477 } \ 1478 \ 1479 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1480 } 1481 1482 PRECR_QH_PW(sra, 0); 1483 PRECR_QH_PW(sra_r, 1); 1484 1485 #undef PRECR_QH_PW 1486 1487 target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt) 1488 { 1489 uint8_t rs6, rs4, rs2, rs0; 1490 uint8_t rt6, rt4, rt2, rt0; 1491 uint64_t temp; 1492 1493 rs6 = (rs >> 56) & MIPSDSP_Q0; 1494 rs4 = (rs >> 40) & MIPSDSP_Q0; 1495 rs2 = (rs >> 24) & MIPSDSP_Q0; 1496 rs0 = (rs >> 8) & MIPSDSP_Q0; 1497 rt6 = (rt >> 56) & MIPSDSP_Q0; 1498 rt4 = (rt >> 40) & MIPSDSP_Q0; 1499 rt2 = (rt >> 24) & MIPSDSP_Q0; 1500 rt0 = (rt >> 8) & MIPSDSP_Q0; 1501 1502 temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) | 1503 ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) | 1504 ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) | 1505 ((uint64_t)rt2 << 8) | (uint64_t)rt0; 1506 1507 return temp; 1508 } 1509 1510 target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt) 1511 { 1512 uint16_t tempD, tempC, tempB, tempA; 1513 1514 tempD = (rs >> 48) & MIPSDSP_LO; 1515 tempC = (rs >> 16) & MIPSDSP_LO; 1516 tempB = (rt >> 48) & MIPSDSP_LO; 1517 tempA = (rt >> 16) & MIPSDSP_LO; 1518 1519 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); 1520 } 1521 1522 target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt, 1523 CPUMIPSState *env) 1524 { 1525 uint32_t rs2, rs0; 1526 uint32_t rt2, rt0; 1527 uint16_t tempD, tempC, tempB, tempA; 1528 1529 rs2 = (rs >> 32) & MIPSDSP_LLO; 1530 rs0 = rs & MIPSDSP_LLO; 1531 rt2 = (rt >> 32) & MIPSDSP_LLO; 1532 rt0 = rt & MIPSDSP_LLO; 1533 1534 tempD = mipsdsp_trunc16_sat16_round(rs2, env); 1535 tempC = mipsdsp_trunc16_sat16_round(rs0, env); 1536 tempB = mipsdsp_trunc16_sat16_round(rt2, env); 1537 tempA = mipsdsp_trunc16_sat16_round(rt0, env); 1538 1539 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); 1540 } 1541 1542 target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt) 1543 { 1544 uint32_t tempB, tempA; 1545 1546 tempB = (rs >> 32) & MIPSDSP_LLO; 1547 tempA = (rt >> 32) & MIPSDSP_LLO; 1548 1549 return MIPSDSP_RETURN64_32(tempB, tempA); 1550 } 1551 #endif 1552 1553 target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt, 1554 CPUMIPSState *env) 1555 { 1556 uint8_t tempD, tempC, tempB, tempA; 1557 uint16_t rsh, rsl, rth, rtl; 1558 1559 rsh = (rs & MIPSDSP_HI) >> 16; 1560 rsl = rs & MIPSDSP_LO; 1561 rth = (rt & MIPSDSP_HI) >> 16; 1562 rtl = rt & MIPSDSP_LO; 1563 1564 tempD = mipsdsp_sat8_reduce_precision(rsh, env); 1565 tempC = mipsdsp_sat8_reduce_precision(rsl, env); 1566 tempB = mipsdsp_sat8_reduce_precision(rth, env); 1567 tempA = mipsdsp_sat8_reduce_precision(rtl, env); 1568 1569 return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); 1570 } 1571 1572 #if defined(TARGET_MIPS64) 1573 target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt, 1574 CPUMIPSState *env) 1575 { 1576 int i; 1577 uint16_t rs3, rs2, rs1, rs0; 1578 uint16_t rt3, rt2, rt1, rt0; 1579 uint8_t temp[8]; 1580 uint64_t result; 1581 1582 result = 0; 1583 1584 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); 1585 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); 1586 1587 temp[7] = mipsdsp_sat8_reduce_precision(rs3, env); 1588 temp[6] = mipsdsp_sat8_reduce_precision(rs2, env); 1589 temp[5] = mipsdsp_sat8_reduce_precision(rs1, env); 1590 temp[4] = mipsdsp_sat8_reduce_precision(rs0, env); 1591 temp[3] = mipsdsp_sat8_reduce_precision(rt3, env); 1592 temp[2] = mipsdsp_sat8_reduce_precision(rt2, env); 1593 temp[1] = mipsdsp_sat8_reduce_precision(rt1, env); 1594 temp[0] = mipsdsp_sat8_reduce_precision(rt0, env); 1595 1596 for (i = 0; i < 8; i++) { 1597 result |= (uint64_t)temp[i] << (8 * i); 1598 } 1599 1600 return result; 1601 } 1602 1603 #define PRECEQ_PW(name, a, b) \ 1604 target_ulong helper_preceq_pw_##name(target_ulong rt) \ 1605 { \ 1606 uint16_t tempB, tempA; \ 1607 uint32_t tempBI, tempAI; \ 1608 \ 1609 tempB = (rt >> a) & MIPSDSP_LO; \ 1610 tempA = (rt >> b) & MIPSDSP_LO; \ 1611 \ 1612 tempBI = (uint32_t)tempB << 16; \ 1613 tempAI = (uint32_t)tempA << 16; \ 1614 \ 1615 return MIPSDSP_RETURN64_32(tempBI, tempAI); \ 1616 } 1617 1618 PRECEQ_PW(qhl, 48, 32); 1619 PRECEQ_PW(qhr, 16, 0); 1620 PRECEQ_PW(qhla, 48, 16); 1621 PRECEQ_PW(qhra, 32, 0); 1622 1623 #undef PRECEQ_PW 1624 1625 #endif 1626 1627 #define PRECEQU_PH(name, a, b) \ 1628 target_ulong helper_precequ_ph_##name(target_ulong rt) \ 1629 { \ 1630 uint16_t tempB, tempA; \ 1631 \ 1632 tempB = (rt >> a) & MIPSDSP_Q0; \ 1633 tempA = (rt >> b) & MIPSDSP_Q0; \ 1634 \ 1635 tempB = tempB << 7; \ 1636 tempA = tempA << 7; \ 1637 \ 1638 return MIPSDSP_RETURN32_16(tempB, tempA); \ 1639 } 1640 1641 PRECEQU_PH(qbl, 24, 16); 1642 PRECEQU_PH(qbr, 8, 0); 1643 PRECEQU_PH(qbla, 24, 8); 1644 PRECEQU_PH(qbra, 16, 0); 1645 1646 #undef PRECEQU_PH 1647 1648 #if defined(TARGET_MIPS64) 1649 #define PRECEQU_QH(name, a, b, c, d) \ 1650 target_ulong helper_precequ_qh_##name(target_ulong rt) \ 1651 { \ 1652 uint16_t tempD, tempC, tempB, tempA; \ 1653 \ 1654 tempD = (rt >> a) & MIPSDSP_Q0; \ 1655 tempC = (rt >> b) & MIPSDSP_Q0; \ 1656 tempB = (rt >> c) & MIPSDSP_Q0; \ 1657 tempA = (rt >> d) & MIPSDSP_Q0; \ 1658 \ 1659 tempD = tempD << 7; \ 1660 tempC = tempC << 7; \ 1661 tempB = tempB << 7; \ 1662 tempA = tempA << 7; \ 1663 \ 1664 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1665 } 1666 1667 PRECEQU_QH(obl, 56, 48, 40, 32); 1668 PRECEQU_QH(obr, 24, 16, 8, 0); 1669 PRECEQU_QH(obla, 56, 40, 24, 8); 1670 PRECEQU_QH(obra, 48, 32, 16, 0); 1671 1672 #undef PRECEQU_QH 1673 1674 #endif 1675 1676 #define PRECEU_PH(name, a, b) \ 1677 target_ulong helper_preceu_ph_##name(target_ulong rt) \ 1678 { \ 1679 uint16_t tempB, tempA; \ 1680 \ 1681 tempB = (rt >> a) & MIPSDSP_Q0; \ 1682 tempA = (rt >> b) & MIPSDSP_Q0; \ 1683 \ 1684 return MIPSDSP_RETURN32_16(tempB, tempA); \ 1685 } 1686 1687 PRECEU_PH(qbl, 24, 16); 1688 PRECEU_PH(qbr, 8, 0); 1689 PRECEU_PH(qbla, 24, 8); 1690 PRECEU_PH(qbra, 16, 0); 1691 1692 #undef PRECEU_PH 1693 1694 #if defined(TARGET_MIPS64) 1695 #define PRECEU_QH(name, a, b, c, d) \ 1696 target_ulong helper_preceu_qh_##name(target_ulong rt) \ 1697 { \ 1698 uint16_t tempD, tempC, tempB, tempA; \ 1699 \ 1700 tempD = (rt >> a) & MIPSDSP_Q0; \ 1701 tempC = (rt >> b) & MIPSDSP_Q0; \ 1702 tempB = (rt >> c) & MIPSDSP_Q0; \ 1703 tempA = (rt >> d) & MIPSDSP_Q0; \ 1704 \ 1705 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 1706 } 1707 1708 PRECEU_QH(obl, 56, 48, 40, 32); 1709 PRECEU_QH(obr, 24, 16, 8, 0); 1710 PRECEU_QH(obla, 56, 40, 24, 8); 1711 PRECEU_QH(obra, 48, 32, 16, 0); 1712 1713 #undef PRECEU_QH 1714 1715 #endif 1716 1717 /** DSP GPR-Based Shift Sub-class insns **/ 1718 #define SHIFT_QB(name, func) \ 1719 target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \ 1720 { \ 1721 uint8_t rt3, rt2, rt1, rt0; \ 1722 \ 1723 sa = sa & 0x07; \ 1724 \ 1725 MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 1726 \ 1727 rt3 = mipsdsp_##func(rt3, sa); \ 1728 rt2 = mipsdsp_##func(rt2, sa); \ 1729 rt1 = mipsdsp_##func(rt1, sa); \ 1730 rt0 = mipsdsp_##func(rt0, sa); \ 1731 \ 1732 return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \ 1733 } 1734 1735 #define SHIFT_QB_ENV(name, func) \ 1736 target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\ 1737 CPUMIPSState *env) \ 1738 { \ 1739 uint8_t rt3, rt2, rt1, rt0; \ 1740 \ 1741 sa = sa & 0x07; \ 1742 \ 1743 MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \ 1744 \ 1745 rt3 = mipsdsp_##func(rt3, sa, env); \ 1746 rt2 = mipsdsp_##func(rt2, sa, env); \ 1747 rt1 = mipsdsp_##func(rt1, sa, env); \ 1748 rt0 = mipsdsp_##func(rt0, sa, env); \ 1749 \ 1750 return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \ 1751 } 1752 1753 SHIFT_QB_ENV(shll, lshift8); 1754 SHIFT_QB(shrl, rshift_u8); 1755 1756 SHIFT_QB(shra, rashift8); 1757 SHIFT_QB(shra_r, rnd8_rashift); 1758 1759 #undef SHIFT_QB 1760 #undef SHIFT_QB_ENV 1761 1762 #if defined(TARGET_MIPS64) 1763 #define SHIFT_OB(name, func) \ 1764 target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \ 1765 { \ 1766 int i; \ 1767 uint8_t rt_t[8]; \ 1768 uint64_t temp; \ 1769 \ 1770 sa = sa & 0x07; \ 1771 temp = 0; \ 1772 \ 1773 for (i = 0; i < 8; i++) { \ 1774 rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ 1775 rt_t[i] = mipsdsp_##func(rt_t[i], sa); \ 1776 temp |= (uint64_t)rt_t[i] << (8 * i); \ 1777 } \ 1778 \ 1779 return temp; \ 1780 } 1781 1782 #define SHIFT_OB_ENV(name, func) \ 1783 target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \ 1784 CPUMIPSState *env) \ 1785 { \ 1786 int i; \ 1787 uint8_t rt_t[8]; \ 1788 uint64_t temp; \ 1789 \ 1790 sa = sa & 0x07; \ 1791 temp = 0; \ 1792 \ 1793 for (i = 0; i < 8; i++) { \ 1794 rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \ 1795 rt_t[i] = mipsdsp_##func(rt_t[i], sa, env); \ 1796 temp |= (uint64_t)rt_t[i] << (8 * i); \ 1797 } \ 1798 \ 1799 return temp; \ 1800 } 1801 1802 SHIFT_OB_ENV(shll, lshift8); 1803 SHIFT_OB(shrl, rshift_u8); 1804 1805 SHIFT_OB(shra, rashift8); 1806 SHIFT_OB(shra_r, rnd8_rashift); 1807 1808 #undef SHIFT_OB 1809 #undef SHIFT_OB_ENV 1810 1811 #endif 1812 1813 #define SHIFT_PH(name, func) \ 1814 target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \ 1815 CPUMIPSState *env) \ 1816 { \ 1817 uint16_t rth, rtl; \ 1818 \ 1819 sa = sa & 0x0F; \ 1820 \ 1821 MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 1822 \ 1823 rth = mipsdsp_##func(rth, sa, env); \ 1824 rtl = mipsdsp_##func(rtl, sa, env); \ 1825 \ 1826 return MIPSDSP_RETURN32_16(rth, rtl); \ 1827 } 1828 1829 SHIFT_PH(shll, lshift16); 1830 SHIFT_PH(shll_s, sat16_lshift); 1831 1832 #undef SHIFT_PH 1833 1834 #if defined(TARGET_MIPS64) 1835 #define SHIFT_QH(name, func) \ 1836 target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \ 1837 { \ 1838 uint16_t rt3, rt2, rt1, rt0; \ 1839 \ 1840 sa = sa & 0x0F; \ 1841 \ 1842 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 1843 \ 1844 rt3 = mipsdsp_##func(rt3, sa); \ 1845 rt2 = mipsdsp_##func(rt2, sa); \ 1846 rt1 = mipsdsp_##func(rt1, sa); \ 1847 rt0 = mipsdsp_##func(rt0, sa); \ 1848 \ 1849 return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \ 1850 } 1851 1852 #define SHIFT_QH_ENV(name, func) \ 1853 target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \ 1854 CPUMIPSState *env) \ 1855 { \ 1856 uint16_t rt3, rt2, rt1, rt0; \ 1857 \ 1858 sa = sa & 0x0F; \ 1859 \ 1860 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 1861 \ 1862 rt3 = mipsdsp_##func(rt3, sa, env); \ 1863 rt2 = mipsdsp_##func(rt2, sa, env); \ 1864 rt1 = mipsdsp_##func(rt1, sa, env); \ 1865 rt0 = mipsdsp_##func(rt0, sa, env); \ 1866 \ 1867 return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \ 1868 } 1869 1870 SHIFT_QH_ENV(shll, lshift16); 1871 SHIFT_QH_ENV(shll_s, sat16_lshift); 1872 1873 SHIFT_QH(shrl, rshift_u16); 1874 SHIFT_QH(shra, rashift16); 1875 SHIFT_QH(shra_r, rnd16_rashift); 1876 1877 #undef SHIFT_QH 1878 #undef SHIFT_QH_ENV 1879 1880 #endif 1881 1882 #define SHIFT_W(name, func) \ 1883 target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \ 1884 { \ 1885 uint32_t temp; \ 1886 \ 1887 sa = sa & 0x1F; \ 1888 temp = mipsdsp_##func(rt, sa); \ 1889 \ 1890 return (target_long)(int32_t)temp; \ 1891 } 1892 1893 #define SHIFT_W_ENV(name, func) \ 1894 target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \ 1895 CPUMIPSState *env) \ 1896 { \ 1897 uint32_t temp; \ 1898 \ 1899 sa = sa & 0x1F; \ 1900 temp = mipsdsp_##func(rt, sa, env); \ 1901 \ 1902 return (target_long)(int32_t)temp; \ 1903 } 1904 1905 SHIFT_W_ENV(shll_s, sat32_lshift); 1906 SHIFT_W(shra_r, rnd32_rashift); 1907 1908 #undef SHIFT_W 1909 #undef SHIFT_W_ENV 1910 1911 #if defined(TARGET_MIPS64) 1912 #define SHIFT_PW(name, func) \ 1913 target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \ 1914 { \ 1915 uint32_t rt1, rt0; \ 1916 \ 1917 sa = sa & 0x1F; \ 1918 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 1919 \ 1920 rt1 = mipsdsp_##func(rt1, sa); \ 1921 rt0 = mipsdsp_##func(rt0, sa); \ 1922 \ 1923 return MIPSDSP_RETURN64_32(rt1, rt0); \ 1924 } 1925 1926 #define SHIFT_PW_ENV(name, func) \ 1927 target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \ 1928 CPUMIPSState *env) \ 1929 { \ 1930 uint32_t rt1, rt0; \ 1931 \ 1932 sa = sa & 0x1F; \ 1933 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 1934 \ 1935 rt1 = mipsdsp_##func(rt1, sa, env); \ 1936 rt0 = mipsdsp_##func(rt0, sa, env); \ 1937 \ 1938 return MIPSDSP_RETURN64_32(rt1, rt0); \ 1939 } 1940 1941 SHIFT_PW_ENV(shll, lshift32); 1942 SHIFT_PW_ENV(shll_s, sat32_lshift); 1943 1944 SHIFT_PW(shra, rashift32); 1945 SHIFT_PW(shra_r, rnd32_rashift); 1946 1947 #undef SHIFT_PW 1948 #undef SHIFT_PW_ENV 1949 1950 #endif 1951 1952 #define SHIFT_PH(name, func) \ 1953 target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \ 1954 { \ 1955 uint16_t rth, rtl; \ 1956 \ 1957 sa = sa & 0x0F; \ 1958 \ 1959 MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 1960 \ 1961 rth = mipsdsp_##func(rth, sa); \ 1962 rtl = mipsdsp_##func(rtl, sa); \ 1963 \ 1964 return MIPSDSP_RETURN32_16(rth, rtl); \ 1965 } 1966 1967 SHIFT_PH(shrl, rshift_u16); 1968 SHIFT_PH(shra, rashift16); 1969 SHIFT_PH(shra_r, rnd16_rashift); 1970 1971 #undef SHIFT_PH 1972 1973 /** DSP Multiply Sub-class insns **/ 1974 /* 1975 * Return value made up by two 16bits value. 1976 * FIXME give the macro a better name. 1977 */ 1978 #define MUL_RETURN32_16_PH(name, func, \ 1979 rsmov1, rsmov2, rsfilter, \ 1980 rtmov1, rtmov2, rtfilter) \ 1981 target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 1982 CPUMIPSState *env) \ 1983 { \ 1984 uint16_t rsB, rsA, rtB, rtA; \ 1985 \ 1986 rsB = (rs >> rsmov1) & rsfilter; \ 1987 rsA = (rs >> rsmov2) & rsfilter; \ 1988 rtB = (rt >> rtmov1) & rtfilter; \ 1989 rtA = (rt >> rtmov2) & rtfilter; \ 1990 \ 1991 rsB = mipsdsp_##func(rsB, rtB, env); \ 1992 rsA = mipsdsp_##func(rsA, rtA, env); \ 1993 \ 1994 return MIPSDSP_RETURN32_16(rsB, rsA); \ 1995 } 1996 1997 MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \ 1998 24, 16, MIPSDSP_Q0, \ 1999 16, 0, MIPSDSP_LO); 2000 MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \ 2001 8, 0, MIPSDSP_Q0, \ 2002 16, 0, MIPSDSP_LO); 2003 MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \ 2004 16, 0, MIPSDSP_LO, \ 2005 16, 0, MIPSDSP_LO); 2006 MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \ 2007 16, 0, MIPSDSP_LO, \ 2008 16, 0, MIPSDSP_LO); 2009 MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \ 2010 16, 0, MIPSDSP_LO, \ 2011 16, 0, MIPSDSP_LO); 2012 MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \ 2013 16, 0, MIPSDSP_LO, \ 2014 16, 0, MIPSDSP_LO); 2015 2016 #undef MUL_RETURN32_16_PH 2017 2018 #define MUL_RETURN32_32_ph(name, func, movbits) \ 2019 target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2020 CPUMIPSState *env) \ 2021 { \ 2022 int16_t rsh, rth; \ 2023 int32_t temp; \ 2024 \ 2025 rsh = (rs >> movbits) & MIPSDSP_LO; \ 2026 rth = (rt >> movbits) & MIPSDSP_LO; \ 2027 temp = mipsdsp_##func(rsh, rth, env); \ 2028 \ 2029 return (target_long)(int32_t)temp; \ 2030 } 2031 2032 MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16); 2033 MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0); 2034 2035 #undef MUL_RETURN32_32_ph 2036 2037 #define MUL_VOID_PH(name, use_ac_env) \ 2038 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2039 CPUMIPSState *env) \ 2040 { \ 2041 int16_t rsh, rsl, rth, rtl; \ 2042 int32_t tempB, tempA; \ 2043 int64_t acc, dotp; \ 2044 \ 2045 MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ 2046 MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 2047 \ 2048 if (use_ac_env == 1) { \ 2049 tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ 2050 tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env); \ 2051 } else { \ 2052 tempB = mipsdsp_mul_u16_u16(rsh, rth); \ 2053 tempA = mipsdsp_mul_u16_u16(rsl, rtl); \ 2054 } \ 2055 \ 2056 dotp = (int64_t)tempB - (int64_t)tempA; \ 2057 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2058 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2059 dotp = dotp + acc; \ 2060 env->active_tc.HI[ac] = (target_long)(int32_t) \ 2061 ((dotp & MIPSDSP_LHI) >> 32); \ 2062 env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO); \ 2063 } 2064 2065 MUL_VOID_PH(mulsaq_s_w_ph, 1); 2066 MUL_VOID_PH(mulsa_w_ph, 0); 2067 2068 #undef MUL_VOID_PH 2069 2070 #if defined(TARGET_MIPS64) 2071 #define MUL_RETURN64_16_QH(name, func, \ 2072 rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \ 2073 rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \ 2074 target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2075 CPUMIPSState *env) \ 2076 { \ 2077 uint16_t rs3, rs2, rs1, rs0; \ 2078 uint16_t rt3, rt2, rt1, rt0; \ 2079 uint16_t tempD, tempC, tempB, tempA; \ 2080 \ 2081 rs3 = (rs >> rsmov1) & rsfilter; \ 2082 rs2 = (rs >> rsmov2) & rsfilter; \ 2083 rs1 = (rs >> rsmov3) & rsfilter; \ 2084 rs0 = (rs >> rsmov4) & rsfilter; \ 2085 rt3 = (rt >> rtmov1) & rtfilter; \ 2086 rt2 = (rt >> rtmov2) & rtfilter; \ 2087 rt1 = (rt >> rtmov3) & rtfilter; \ 2088 rt0 = (rt >> rtmov4) & rtfilter; \ 2089 \ 2090 tempD = mipsdsp_##func(rs3, rt3, env); \ 2091 tempC = mipsdsp_##func(rs2, rt2, env); \ 2092 tempB = mipsdsp_##func(rs1, rt1, env); \ 2093 tempA = mipsdsp_##func(rs0, rt0, env); \ 2094 \ 2095 return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \ 2096 } 2097 2098 MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \ 2099 56, 48, 40, 32, MIPSDSP_Q0, \ 2100 48, 32, 16, 0, MIPSDSP_LO); 2101 MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \ 2102 24, 16, 8, 0, MIPSDSP_Q0, \ 2103 48, 32, 16, 0, MIPSDSP_LO); 2104 MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \ 2105 48, 32, 16, 0, MIPSDSP_LO, \ 2106 48, 32, 16, 0, MIPSDSP_LO); 2107 2108 #undef MUL_RETURN64_16_QH 2109 2110 #define MUL_RETURN64_32_QH(name, \ 2111 rsmov1, rsmov2, \ 2112 rtmov1, rtmov2) \ 2113 target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2114 CPUMIPSState *env) \ 2115 { \ 2116 uint16_t rsB, rsA; \ 2117 uint16_t rtB, rtA; \ 2118 uint32_t tempB, tempA; \ 2119 \ 2120 rsB = (rs >> rsmov1) & MIPSDSP_LO; \ 2121 rsA = (rs >> rsmov2) & MIPSDSP_LO; \ 2122 rtB = (rt >> rtmov1) & MIPSDSP_LO; \ 2123 rtA = (rt >> rtmov2) & MIPSDSP_LO; \ 2124 \ 2125 tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env); \ 2126 tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env); \ 2127 \ 2128 return ((uint64_t)tempB << 32) | (uint64_t)tempA; \ 2129 } 2130 2131 MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32); 2132 MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0); 2133 2134 #undef MUL_RETURN64_32_QH 2135 2136 void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac, 2137 CPUMIPSState *env) 2138 { 2139 int16_t rs3, rs2, rs1, rs0; 2140 int16_t rt3, rt2, rt1, rt0; 2141 int32_t tempD, tempC, tempB, tempA; 2142 int64_t acc[2]; 2143 int64_t temp[2]; 2144 int64_t temp_sum; 2145 2146 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); 2147 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); 2148 2149 tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); 2150 tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); 2151 tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); 2152 tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); 2153 2154 temp[0] = ((int32_t)tempD - (int32_t)tempC) + 2155 ((int32_t)tempB - (int32_t)tempA); 2156 temp[0] = (int64_t)(temp[0] << 30) >> 30; 2157 if (((temp[0] >> 33) & 0x01) == 0) { 2158 temp[1] = 0x00; 2159 } else { 2160 temp[1] = ~0ull; 2161 } 2162 2163 acc[0] = env->active_tc.LO[ac]; 2164 acc[1] = env->active_tc.HI[ac]; 2165 2166 temp_sum = acc[0] + temp[0]; 2167 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && 2168 ((uint64_t)temp_sum < (uint64_t)temp[0])) { 2169 acc[1] += 1; 2170 } 2171 acc[0] = temp_sum; 2172 acc[1] += temp[1]; 2173 2174 env->active_tc.HI[ac] = acc[1]; 2175 env->active_tc.LO[ac] = acc[0]; 2176 } 2177 #endif 2178 2179 #define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ 2180 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2181 CPUMIPSState *env) \ 2182 { \ 2183 uint8_t rs3, rs2; \ 2184 uint8_t rt3, rt2; \ 2185 uint16_t tempB, tempA; \ 2186 uint64_t tempC, dotp; \ 2187 \ 2188 rs3 = (rs >> rsmov1) & MIPSDSP_Q0; \ 2189 rs2 = (rs >> rsmov2) & MIPSDSP_Q0; \ 2190 rt3 = (rt >> rtmov1) & MIPSDSP_Q0; \ 2191 rt2 = (rt >> rtmov2) & MIPSDSP_Q0; \ 2192 tempB = mipsdsp_##func(rs3, rt3); \ 2193 tempA = mipsdsp_##func(rs2, rt2); \ 2194 dotp = (int64_t)tempB + (int64_t)tempA; \ 2195 if (is_add) { \ 2196 tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \ 2197 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \ 2198 + dotp; \ 2199 } else { \ 2200 tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \ 2201 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \ 2202 - dotp; \ 2203 } \ 2204 \ 2205 env->active_tc.HI[ac] = (target_long)(int32_t) \ 2206 ((tempC & MIPSDSP_LHI) >> 32); \ 2207 env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \ 2208 } 2209 2210 DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16); 2211 DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0); 2212 DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16); 2213 DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0); 2214 2215 #undef DP_QB 2216 2217 #if defined(TARGET_MIPS64) 2218 #define DP_OB(name, add_sub, \ 2219 rsmov1, rsmov2, rsmov3, rsmov4, \ 2220 rtmov1, rtmov2, rtmov3, rtmov4) \ 2221 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2222 CPUMIPSState *env) \ 2223 { \ 2224 uint8_t rsD, rsC, rsB, rsA; \ 2225 uint8_t rtD, rtC, rtB, rtA; \ 2226 uint16_t tempD, tempC, tempB, tempA; \ 2227 uint64_t temp[2]; \ 2228 uint64_t acc[2]; \ 2229 uint64_t temp_sum; \ 2230 \ 2231 temp[0] = 0; \ 2232 temp[1] = 0; \ 2233 \ 2234 rsD = (rs >> rsmov1) & MIPSDSP_Q0; \ 2235 rsC = (rs >> rsmov2) & MIPSDSP_Q0; \ 2236 rsB = (rs >> rsmov3) & MIPSDSP_Q0; \ 2237 rsA = (rs >> rsmov4) & MIPSDSP_Q0; \ 2238 rtD = (rt >> rtmov1) & MIPSDSP_Q0; \ 2239 rtC = (rt >> rtmov2) & MIPSDSP_Q0; \ 2240 rtB = (rt >> rtmov3) & MIPSDSP_Q0; \ 2241 rtA = (rt >> rtmov4) & MIPSDSP_Q0; \ 2242 \ 2243 tempD = mipsdsp_mul_u8_u8(rsD, rtD); \ 2244 tempC = mipsdsp_mul_u8_u8(rsC, rtC); \ 2245 tempB = mipsdsp_mul_u8_u8(rsB, rtB); \ 2246 tempA = mipsdsp_mul_u8_u8(rsA, rtA); \ 2247 \ 2248 temp[0] = (uint64_t)tempD + (uint64_t)tempC + \ 2249 (uint64_t)tempB + (uint64_t)tempA; \ 2250 \ 2251 acc[0] = env->active_tc.LO[ac]; \ 2252 acc[1] = env->active_tc.HI[ac]; \ 2253 \ 2254 if (add_sub) { \ 2255 temp_sum = acc[0] + temp[0]; \ 2256 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2257 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2258 acc[1] += 1; \ 2259 } \ 2260 temp[0] = temp_sum; \ 2261 temp[1] = acc[1] + temp[1]; \ 2262 } else { \ 2263 temp_sum = acc[0] - temp[0]; \ 2264 if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ 2265 acc[1] -= 1; \ 2266 } \ 2267 temp[0] = temp_sum; \ 2268 temp[1] = acc[1] - temp[1]; \ 2269 } \ 2270 \ 2271 env->active_tc.HI[ac] = temp[1]; \ 2272 env->active_tc.LO[ac] = temp[0]; \ 2273 } 2274 2275 DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32); 2276 DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0); 2277 DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32); 2278 DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0); 2279 2280 #undef DP_OB 2281 #endif 2282 2283 #define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ 2284 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2285 CPUMIPSState *env) \ 2286 { \ 2287 int16_t rsB, rsA, rtB, rtA; \ 2288 int32_t tempA, tempB; \ 2289 int64_t acc; \ 2290 \ 2291 rsB = (rs >> rsmov1) & MIPSDSP_LO; \ 2292 rsA = (rs >> rsmov2) & MIPSDSP_LO; \ 2293 rtB = (rt >> rtmov1) & MIPSDSP_LO; \ 2294 rtA = (rt >> rtmov2) & MIPSDSP_LO; \ 2295 \ 2296 tempB = (int32_t)rsB * (int32_t)rtB; \ 2297 tempA = (int32_t)rsA * (int32_t)rtA; \ 2298 \ 2299 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2300 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2301 \ 2302 if (is_add) { \ 2303 acc = acc + ((int64_t)tempB + (int64_t)tempA); \ 2304 } else { \ 2305 acc = acc - ((int64_t)tempB + (int64_t)tempA); \ 2306 } \ 2307 \ 2308 env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \ 2309 env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO); \ 2310 } 2311 2312 DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0); 2313 DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16); 2314 DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0); 2315 DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16); 2316 #undef DP_NOFUNC_PH 2317 2318 #define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \ 2319 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2320 CPUMIPSState *env) \ 2321 { \ 2322 int16_t rsB, rsA, rtB, rtA; \ 2323 int32_t tempB, tempA; \ 2324 int64_t acc, dotp; \ 2325 \ 2326 rsB = (rs >> rsmov1) & MIPSDSP_LO; \ 2327 rsA = (rs >> rsmov2) & MIPSDSP_LO; \ 2328 rtB = (rt >> rtmov1) & MIPSDSP_LO; \ 2329 rtA = (rt >> rtmov2) & MIPSDSP_LO; \ 2330 \ 2331 tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env); \ 2332 tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env); \ 2333 \ 2334 dotp = (int64_t)tempB + (int64_t)tempA; \ 2335 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2336 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2337 \ 2338 if (is_add) { \ 2339 acc = acc + dotp; \ 2340 } else { \ 2341 acc = acc - dotp; \ 2342 } \ 2343 \ 2344 env->active_tc.HI[ac] = (target_long)(int32_t) \ 2345 ((acc & MIPSDSP_LHI) >> 32); \ 2346 env->active_tc.LO[ac] = (target_long)(int32_t) \ 2347 (acc & MIPSDSP_LLO); \ 2348 } 2349 2350 DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0); 2351 DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16); 2352 DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0); 2353 DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16); 2354 2355 #undef DP_HASFUNC_PH 2356 2357 #define DP_128OPERATION_PH(name, is_add) \ 2358 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2359 CPUMIPSState *env) \ 2360 { \ 2361 int16_t rsh, rsl, rth, rtl; \ 2362 int32_t tempB, tempA, tempC62_31, tempC63; \ 2363 int64_t acc, dotp, tempC; \ 2364 \ 2365 MIPSDSP_SPLIT32_16(rs, rsh, rsl); \ 2366 MIPSDSP_SPLIT32_16(rt, rth, rtl); \ 2367 \ 2368 tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env); \ 2369 tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env); \ 2370 \ 2371 dotp = (int64_t)tempB + (int64_t)tempA; \ 2372 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2373 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2374 if (is_add) { \ 2375 tempC = acc + dotp; \ 2376 } else { \ 2377 tempC = acc - dotp; \ 2378 } \ 2379 tempC63 = (tempC >> 63) & 0x01; \ 2380 tempC62_31 = (tempC >> 31) & 0xFFFFFFFF; \ 2381 \ 2382 if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) { \ 2383 tempC = 0x7FFFFFFF; \ 2384 set_DSPControl_overflow_flag(1, 16 + ac, env); \ 2385 } \ 2386 \ 2387 if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) { \ 2388 tempC = (int64_t)(int32_t)0x80000000; \ 2389 set_DSPControl_overflow_flag(1, 16 + ac, env); \ 2390 } \ 2391 \ 2392 env->active_tc.HI[ac] = (target_long)(int32_t) \ 2393 ((tempC & MIPSDSP_LHI) >> 32); \ 2394 env->active_tc.LO[ac] = (target_long)(int32_t) \ 2395 (tempC & MIPSDSP_LLO); \ 2396 } 2397 2398 DP_128OPERATION_PH(dpaqx_sa_w_ph, 1); 2399 DP_128OPERATION_PH(dpsqx_sa_w_ph, 0); 2400 2401 #undef DP_128OPERATION_HP 2402 2403 #if defined(TARGET_MIPS64) 2404 #define DP_QH(name, is_add, use_ac_env) \ 2405 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2406 CPUMIPSState *env) \ 2407 { \ 2408 int32_t rs3, rs2, rs1, rs0; \ 2409 int32_t rt3, rt2, rt1, rt0; \ 2410 int32_t tempD, tempC, tempB, tempA; \ 2411 int64_t acc[2]; \ 2412 int64_t temp[2]; \ 2413 int64_t temp_sum; \ 2414 \ 2415 MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ 2416 MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ 2417 \ 2418 if (use_ac_env) { \ 2419 tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); \ 2420 tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); \ 2421 tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); \ 2422 tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); \ 2423 } else { \ 2424 tempD = mipsdsp_mul_u16_u16(rs3, rt3); \ 2425 tempC = mipsdsp_mul_u16_u16(rs2, rt2); \ 2426 tempB = mipsdsp_mul_u16_u16(rs1, rt1); \ 2427 tempA = mipsdsp_mul_u16_u16(rs0, rt0); \ 2428 } \ 2429 \ 2430 temp[0] = (int64_t)tempD + (int64_t)tempC + \ 2431 (int64_t)tempB + (int64_t)tempA; \ 2432 \ 2433 if (temp[0] >= 0) { \ 2434 temp[1] = 0; \ 2435 } else { \ 2436 temp[1] = ~0ull; \ 2437 } \ 2438 \ 2439 acc[1] = env->active_tc.HI[ac]; \ 2440 acc[0] = env->active_tc.LO[ac]; \ 2441 \ 2442 if (is_add) { \ 2443 temp_sum = acc[0] + temp[0]; \ 2444 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2445 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2446 acc[1] = acc[1] + 1; \ 2447 } \ 2448 temp[0] = temp_sum; \ 2449 temp[1] = acc[1] + temp[1]; \ 2450 } else { \ 2451 temp_sum = acc[0] - temp[0]; \ 2452 if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ 2453 acc[1] = acc[1] - 1; \ 2454 } \ 2455 temp[0] = temp_sum; \ 2456 temp[1] = acc[1] - temp[1]; \ 2457 } \ 2458 \ 2459 env->active_tc.HI[ac] = temp[1]; \ 2460 env->active_tc.LO[ac] = temp[0]; \ 2461 } 2462 2463 DP_QH(dpa_w_qh, 1, 0); 2464 DP_QH(dpaq_s_w_qh, 1, 1); 2465 DP_QH(dps_w_qh, 0, 0); 2466 DP_QH(dpsq_s_w_qh, 0, 1); 2467 2468 #undef DP_QH 2469 2470 #endif 2471 2472 #define DP_L_W(name, is_add) \ 2473 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2474 CPUMIPSState *env) \ 2475 { \ 2476 int32_t temp63; \ 2477 int64_t dotp, acc; \ 2478 uint64_t temp; \ 2479 bool overflow; \ 2480 \ 2481 dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \ 2482 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2483 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2484 if (is_add) { \ 2485 temp = acc + dotp; \ 2486 overflow = MIPSDSP_OVERFLOW_ADD((uint64_t)acc, (uint64_t)dotp, \ 2487 temp, (0x01ull << 63)); \ 2488 } else { \ 2489 temp = acc - dotp; \ 2490 overflow = MIPSDSP_OVERFLOW_SUB((uint64_t)acc, (uint64_t)dotp, \ 2491 temp, (0x01ull << 63)); \ 2492 } \ 2493 \ 2494 if (overflow) { \ 2495 temp63 = (temp >> 63) & 0x01; \ 2496 if (temp63 == 1) { \ 2497 temp = (0x01ull << 63) - 1; \ 2498 } else { \ 2499 temp = 0x01ull << 63; \ 2500 } \ 2501 \ 2502 set_DSPControl_overflow_flag(1, 16 + ac, env); \ 2503 } \ 2504 \ 2505 env->active_tc.HI[ac] = (target_long)(int32_t) \ 2506 ((temp & MIPSDSP_LHI) >> 32); \ 2507 env->active_tc.LO[ac] = (target_long)(int32_t) \ 2508 (temp & MIPSDSP_LLO); \ 2509 } 2510 2511 DP_L_W(dpaq_sa_l_w, 1); 2512 DP_L_W(dpsq_sa_l_w, 0); 2513 2514 #undef DP_L_W 2515 2516 #if defined(TARGET_MIPS64) 2517 #define DP_L_PW(name, func) \ 2518 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2519 CPUMIPSState *env) \ 2520 { \ 2521 int32_t rs1, rs0; \ 2522 int32_t rt1, rt0; \ 2523 int64_t tempB[2], tempA[2]; \ 2524 int64_t temp[2]; \ 2525 int64_t acc[2]; \ 2526 int64_t temp_sum; \ 2527 \ 2528 temp[0] = 0; \ 2529 temp[1] = 0; \ 2530 \ 2531 MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ 2532 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 2533 \ 2534 tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); \ 2535 tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); \ 2536 \ 2537 if (tempB[0] >= 0) { \ 2538 tempB[1] = 0x00; \ 2539 } else { \ 2540 tempB[1] = ~0ull; \ 2541 } \ 2542 \ 2543 if (tempA[0] >= 0) { \ 2544 tempA[1] = 0x00; \ 2545 } else { \ 2546 tempA[1] = ~0ull; \ 2547 } \ 2548 \ 2549 temp_sum = tempB[0] + tempA[0]; \ 2550 if (((uint64_t)temp_sum < (uint64_t)tempB[0]) && \ 2551 ((uint64_t)temp_sum < (uint64_t)tempA[0])) { \ 2552 temp[1] += 1; \ 2553 } \ 2554 temp[0] = temp_sum; \ 2555 temp[1] += tempB[1] + tempA[1]; \ 2556 \ 2557 mipsdsp_##func(acc, ac, temp, env); \ 2558 \ 2559 env->active_tc.HI[ac] = acc[1]; \ 2560 env->active_tc.LO[ac] = acc[0]; \ 2561 } 2562 2563 DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63); 2564 DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63); 2565 2566 #undef DP_L_PW 2567 2568 void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac, 2569 CPUMIPSState *env) 2570 { 2571 int32_t rs1, rs0; 2572 int32_t rt1, rt0; 2573 int64_t tempB[2], tempA[2]; 2574 int64_t temp[2]; 2575 int64_t acc[2]; 2576 int64_t temp_sum; 2577 2578 rs1 = (rs >> 32) & MIPSDSP_LLO; 2579 rs0 = rs & MIPSDSP_LLO; 2580 rt1 = (rt >> 32) & MIPSDSP_LLO; 2581 rt0 = rt & MIPSDSP_LLO; 2582 2583 tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); 2584 tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); 2585 2586 if (tempB[0] >= 0) { 2587 tempB[1] = 0x00; 2588 } else { 2589 tempB[1] = ~0ull; 2590 } 2591 2592 if (tempA[0] >= 0) { 2593 tempA[1] = 0x00; 2594 } else { 2595 tempA[1] = ~0ull; 2596 } 2597 2598 acc[0] = env->active_tc.LO[ac]; 2599 acc[1] = env->active_tc.HI[ac]; 2600 2601 temp_sum = tempB[0] - tempA[0]; 2602 if ((uint64_t)temp_sum > (uint64_t)tempB[0]) { 2603 tempB[1] -= 1; 2604 } 2605 temp[0] = temp_sum; 2606 temp[1] = tempB[1] - tempA[1]; 2607 2608 if ((temp[1] & 0x01) == 0) { 2609 temp[1] = 0x00; 2610 } else { 2611 temp[1] = ~0ull; 2612 } 2613 2614 temp_sum = acc[0] + temp[0]; 2615 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && 2616 ((uint64_t)temp_sum < (uint64_t)temp[0])) { 2617 acc[1] += 1; 2618 } 2619 acc[0] = temp_sum; 2620 acc[1] += temp[1]; 2621 2622 env->active_tc.HI[ac] = acc[1]; 2623 env->active_tc.LO[ac] = acc[0]; 2624 } 2625 #endif 2626 2627 #define MAQ_S_W(name, mov) \ 2628 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2629 CPUMIPSState *env) \ 2630 { \ 2631 int16_t rsh, rth; \ 2632 int32_t tempA; \ 2633 int64_t tempL, acc; \ 2634 \ 2635 rsh = (rs >> mov) & MIPSDSP_LO; \ 2636 rth = (rt >> mov) & MIPSDSP_LO; \ 2637 tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ 2638 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \ 2639 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \ 2640 tempL = (int64_t)tempA + acc; \ 2641 env->active_tc.HI[ac] = (target_long)(int32_t) \ 2642 ((tempL & MIPSDSP_LHI) >> 32); \ 2643 env->active_tc.LO[ac] = (target_long)(int32_t) \ 2644 (tempL & MIPSDSP_LLO); \ 2645 } 2646 2647 MAQ_S_W(maq_s_w_phl, 16); 2648 MAQ_S_W(maq_s_w_phr, 0); 2649 2650 #undef MAQ_S_W 2651 2652 #define MAQ_SA_W(name, mov) \ 2653 void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \ 2654 CPUMIPSState *env) \ 2655 { \ 2656 int16_t rsh, rth; \ 2657 int32_t tempA; \ 2658 \ 2659 rsh = (rs >> mov) & MIPSDSP_LO; \ 2660 rth = (rt >> mov) & MIPSDSP_LO; \ 2661 tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \ 2662 tempA = mipsdsp_sat32_acc_q31(ac, tempA, env); \ 2663 \ 2664 env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA & \ 2665 MIPSDSP_LHI) >> 32); \ 2666 env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA & \ 2667 MIPSDSP_LLO); \ 2668 } 2669 2670 MAQ_SA_W(maq_sa_w_phl, 16); 2671 MAQ_SA_W(maq_sa_w_phr, 0); 2672 2673 #undef MAQ_SA_W 2674 2675 #define MULQ_W(name, addvar) \ 2676 target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 2677 CPUMIPSState *env) \ 2678 { \ 2679 int32_t rs_t, rt_t; \ 2680 int32_t tempI; \ 2681 int64_t tempL; \ 2682 \ 2683 rs_t = rs & MIPSDSP_LLO; \ 2684 rt_t = rt & MIPSDSP_LLO; \ 2685 \ 2686 if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) { \ 2687 tempL = 0x7FFFFFFF00000000ull; \ 2688 set_DSPControl_overflow_flag(1, 21, env); \ 2689 } else { \ 2690 tempL = ((int64_t)rs_t * (int64_t)rt_t) << 1; \ 2691 tempL += addvar; \ 2692 } \ 2693 tempI = (tempL & MIPSDSP_LHI) >> 32; \ 2694 \ 2695 return (target_long)(int32_t)tempI; \ 2696 } 2697 2698 MULQ_W(mulq_s_w, 0); 2699 MULQ_W(mulq_rs_w, 0x80000000ull); 2700 2701 #undef MULQ_W 2702 2703 #if defined(TARGET_MIPS64) 2704 2705 #define MAQ_S_W_QH(name, mov) \ 2706 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2707 CPUMIPSState *env) \ 2708 { \ 2709 int16_t rs_t, rt_t; \ 2710 int32_t temp_mul; \ 2711 int64_t temp[2]; \ 2712 int64_t acc[2]; \ 2713 int64_t temp_sum; \ 2714 \ 2715 temp[0] = 0; \ 2716 temp[1] = 0; \ 2717 \ 2718 rs_t = (rs >> mov) & MIPSDSP_LO; \ 2719 rt_t = (rt >> mov) & MIPSDSP_LO; \ 2720 temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \ 2721 \ 2722 temp[0] = (int64_t)temp_mul; \ 2723 if (temp[0] >= 0) { \ 2724 temp[1] = 0x00; \ 2725 } else { \ 2726 temp[1] = ~0ull; \ 2727 } \ 2728 \ 2729 acc[0] = env->active_tc.LO[ac]; \ 2730 acc[1] = env->active_tc.HI[ac]; \ 2731 \ 2732 temp_sum = acc[0] + temp[0]; \ 2733 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2734 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2735 acc[1] += 1; \ 2736 } \ 2737 acc[0] = temp_sum; \ 2738 acc[1] += temp[1]; \ 2739 \ 2740 env->active_tc.HI[ac] = acc[1]; \ 2741 env->active_tc.LO[ac] = acc[0]; \ 2742 } 2743 2744 MAQ_S_W_QH(maq_s_w_qhll, 48); 2745 MAQ_S_W_QH(maq_s_w_qhlr, 32); 2746 MAQ_S_W_QH(maq_s_w_qhrl, 16); 2747 MAQ_S_W_QH(maq_s_w_qhrr, 0); 2748 2749 #undef MAQ_S_W_QH 2750 2751 #define MAQ_SA_W(name, mov) \ 2752 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2753 CPUMIPSState *env) \ 2754 { \ 2755 int16_t rs_t, rt_t; \ 2756 int32_t temp; \ 2757 int64_t acc[2]; \ 2758 \ 2759 rs_t = (rs >> mov) & MIPSDSP_LO; \ 2760 rt_t = (rt >> mov) & MIPSDSP_LO; \ 2761 temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \ 2762 temp = mipsdsp_sat32_acc_q31(ac, temp, env); \ 2763 \ 2764 acc[0] = (int64_t)(int32_t)temp; \ 2765 if (acc[0] >= 0) { \ 2766 acc[1] = 0x00; \ 2767 } else { \ 2768 acc[1] = ~0ull; \ 2769 } \ 2770 \ 2771 env->active_tc.HI[ac] = acc[1]; \ 2772 env->active_tc.LO[ac] = acc[0]; \ 2773 } 2774 2775 MAQ_SA_W(maq_sa_w_qhll, 48); 2776 MAQ_SA_W(maq_sa_w_qhlr, 32); 2777 MAQ_SA_W(maq_sa_w_qhrl, 16); 2778 MAQ_SA_W(maq_sa_w_qhrr, 0); 2779 2780 #undef MAQ_SA_W 2781 2782 #define MAQ_S_L_PW(name, mov) \ 2783 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2784 CPUMIPSState *env) \ 2785 { \ 2786 int32_t rs_t, rt_t; \ 2787 int64_t temp[2]; \ 2788 int64_t acc[2]; \ 2789 int64_t temp_sum; \ 2790 \ 2791 temp[0] = 0; \ 2792 temp[1] = 0; \ 2793 \ 2794 rs_t = (rs >> mov) & MIPSDSP_LLO; \ 2795 rt_t = (rt >> mov) & MIPSDSP_LLO; \ 2796 \ 2797 temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env); \ 2798 if (temp[0] >= 0) { \ 2799 temp[1] = 0x00; \ 2800 } else { \ 2801 temp[1] = ~0ull; \ 2802 } \ 2803 \ 2804 acc[0] = env->active_tc.LO[ac]; \ 2805 acc[1] = env->active_tc.HI[ac]; \ 2806 \ 2807 temp_sum = acc[0] + temp[0]; \ 2808 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2809 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2810 acc[1] += 1; \ 2811 } \ 2812 acc[0] = temp_sum; \ 2813 acc[1] += temp[1]; \ 2814 \ 2815 env->active_tc.HI[ac] = acc[1]; \ 2816 env->active_tc.LO[ac] = acc[0]; \ 2817 } 2818 2819 MAQ_S_L_PW(maq_s_l_pwl, 32); 2820 MAQ_S_L_PW(maq_s_l_pwr, 0); 2821 2822 #undef MAQ_S_L_PW 2823 2824 #define DM_OPERATE(name, func, is_add, sigext) \ 2825 void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \ 2826 CPUMIPSState *env) \ 2827 { \ 2828 int32_t rs1, rs0; \ 2829 int32_t rt1, rt0; \ 2830 int64_t tempBL[2], tempAL[2]; \ 2831 int64_t acc[2]; \ 2832 int64_t temp[2]; \ 2833 int64_t temp_sum; \ 2834 \ 2835 temp[0] = 0x00; \ 2836 temp[1] = 0x00; \ 2837 \ 2838 MIPSDSP_SPLIT64_32(rs, rs1, rs0); \ 2839 MIPSDSP_SPLIT64_32(rt, rt1, rt0); \ 2840 \ 2841 if (sigext) { \ 2842 tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1); \ 2843 tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0); \ 2844 \ 2845 if (tempBL[0] >= 0) { \ 2846 tempBL[1] = 0x0; \ 2847 } else { \ 2848 tempBL[1] = ~0ull; \ 2849 } \ 2850 \ 2851 if (tempAL[0] >= 0) { \ 2852 tempAL[1] = 0x0; \ 2853 } else { \ 2854 tempAL[1] = ~0ull; \ 2855 } \ 2856 } else { \ 2857 tempBL[0] = mipsdsp_##func(rs1, rt1); \ 2858 tempAL[0] = mipsdsp_##func(rs0, rt0); \ 2859 tempBL[1] = 0; \ 2860 tempAL[1] = 0; \ 2861 } \ 2862 \ 2863 acc[1] = env->active_tc.HI[ac]; \ 2864 acc[0] = env->active_tc.LO[ac]; \ 2865 \ 2866 temp_sum = tempBL[0] + tempAL[0]; \ 2867 if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) && \ 2868 ((uint64_t)temp_sum < (uint64_t)tempAL[0])) { \ 2869 temp[1] += 1; \ 2870 } \ 2871 temp[0] = temp_sum; \ 2872 temp[1] += tempBL[1] + tempAL[1]; \ 2873 \ 2874 if (is_add) { \ 2875 temp_sum = acc[0] + temp[0]; \ 2876 if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \ 2877 ((uint64_t)temp_sum < (uint64_t)temp[0])) { \ 2878 acc[1] += 1; \ 2879 } \ 2880 temp[0] = temp_sum; \ 2881 temp[1] = acc[1] + temp[1]; \ 2882 } else { \ 2883 temp_sum = acc[0] - temp[0]; \ 2884 if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \ 2885 acc[1] -= 1; \ 2886 } \ 2887 temp[0] = temp_sum; \ 2888 temp[1] = acc[1] - temp[1]; \ 2889 } \ 2890 \ 2891 env->active_tc.HI[ac] = temp[1]; \ 2892 env->active_tc.LO[ac] = temp[0]; \ 2893 } 2894 2895 DM_OPERATE(dmadd, mul_i32_i32, 1, 1); 2896 DM_OPERATE(dmaddu, mul_u32_u32, 1, 0); 2897 DM_OPERATE(dmsub, mul_i32_i32, 0, 1); 2898 DM_OPERATE(dmsubu, mul_u32_u32, 0, 0); 2899 #undef DM_OPERATE 2900 #endif 2901 2902 /** DSP Bit/Manipulation Sub-class insns **/ 2903 target_ulong helper_bitrev(target_ulong rt) 2904 { 2905 int32_t temp; 2906 uint32_t rd; 2907 int i; 2908 2909 temp = rt & MIPSDSP_LO; 2910 rd = 0; 2911 for (i = 0; i < 16; i++) { 2912 rd = (rd << 1) | (temp & 1); 2913 temp = temp >> 1; 2914 } 2915 2916 return (target_ulong)rd; 2917 } 2918 2919 #define BIT_INSV(name, posfilter, ret_type) \ 2920 target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \ 2921 target_ulong rt) \ 2922 { \ 2923 uint32_t pos, size, msb, lsb; \ 2924 uint32_t const sizefilter = 0x3F; \ 2925 target_ulong temp; \ 2926 target_ulong dspc; \ 2927 \ 2928 dspc = env->active_tc.DSPControl; \ 2929 \ 2930 pos = dspc & posfilter; \ 2931 size = (dspc >> 7) & sizefilter; \ 2932 \ 2933 msb = pos + size - 1; \ 2934 lsb = pos; \ 2935 \ 2936 if (lsb > msb || (msb > TARGET_LONG_BITS)) { \ 2937 return rt; \ 2938 } \ 2939 \ 2940 temp = deposit64(rt, pos, size, rs); \ 2941 \ 2942 return (target_long)(ret_type)temp; \ 2943 } 2944 2945 BIT_INSV(insv, 0x1F, int32_t); 2946 #ifdef TARGET_MIPS64 2947 BIT_INSV(dinsv, 0x7F, target_long); 2948 #endif 2949 2950 #undef BIT_INSV 2951 2952 2953 /** DSP Compare-Pick Sub-class insns **/ 2954 #define CMP_HAS_RET(name, func, split_num, filter, bit_size) \ 2955 target_ulong helper_##name(target_ulong rs, target_ulong rt) \ 2956 { \ 2957 uint32_t rs_t, rt_t; \ 2958 uint8_t cc; \ 2959 uint32_t temp = 0; \ 2960 int i; \ 2961 \ 2962 for (i = 0; i < split_num; i++) { \ 2963 rs_t = (rs >> (bit_size * i)) & filter; \ 2964 rt_t = (rt >> (bit_size * i)) & filter; \ 2965 cc = mipsdsp_##func(rs_t, rt_t); \ 2966 temp |= cc << i; \ 2967 } \ 2968 \ 2969 return (target_ulong)temp; \ 2970 } 2971 2972 CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); 2973 CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); 2974 CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); 2975 2976 #ifdef TARGET_MIPS64 2977 CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); 2978 CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); 2979 CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8); 2980 #endif 2981 2982 #undef CMP_HAS_RET 2983 2984 2985 #define CMP_NO_RET(name, func, split_num, filter, bit_size) \ 2986 void helper_##name(target_ulong rs, target_ulong rt, \ 2987 CPUMIPSState *env) \ 2988 { \ 2989 int##bit_size##_t rs_t, rt_t; \ 2990 int##bit_size##_t flag = 0; \ 2991 int##bit_size##_t cc; \ 2992 int i; \ 2993 \ 2994 for (i = 0; i < split_num; i++) { \ 2995 rs_t = (rs >> (bit_size * i)) & filter; \ 2996 rt_t = (rt >> (bit_size * i)) & filter; \ 2997 \ 2998 cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t); \ 2999 flag |= cc << i; \ 3000 } \ 3001 \ 3002 set_DSPControl_24(flag, split_num, env); \ 3003 } 3004 3005 CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); 3006 CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); 3007 CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); 3008 3009 CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16); 3010 CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16); 3011 CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16); 3012 3013 #ifdef TARGET_MIPS64 3014 CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); 3015 CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); 3016 CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8); 3017 3018 CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16); 3019 CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16); 3020 CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16); 3021 3022 CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32); 3023 CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32); 3024 CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32); 3025 #endif 3026 #undef CMP_NO_RET 3027 3028 #if defined(TARGET_MIPS64) 3029 3030 #define CMPGDU_OB(name) \ 3031 target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \ 3032 CPUMIPSState *env) \ 3033 { \ 3034 int i; \ 3035 uint8_t rs_t, rt_t; \ 3036 uint32_t cond; \ 3037 \ 3038 cond = 0; \ 3039 \ 3040 for (i = 0; i < 8; i++) { \ 3041 rs_t = (rs >> (8 * i)) & MIPSDSP_Q0; \ 3042 rt_t = (rt >> (8 * i)) & MIPSDSP_Q0; \ 3043 \ 3044 if (mipsdsp_cmpu_##name(rs_t, rt_t)) { \ 3045 cond |= 0x01 << i; \ 3046 } \ 3047 } \ 3048 \ 3049 set_DSPControl_24(cond, 8, env); \ 3050 \ 3051 return (uint64_t)cond; \ 3052 } 3053 3054 CMPGDU_OB(eq) 3055 CMPGDU_OB(lt) 3056 CMPGDU_OB(le) 3057 #undef CMPGDU_OB 3058 #endif 3059 3060 #define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \ 3061 target_ulong helper_##name(target_ulong rs, target_ulong rt, \ 3062 CPUMIPSState *env) \ 3063 { \ 3064 uint32_t rs_t, rt_t; \ 3065 uint32_t cc; \ 3066 target_ulong dsp; \ 3067 int i; \ 3068 target_ulong result = 0; \ 3069 \ 3070 dsp = env->active_tc.DSPControl; \ 3071 for (i = 0; i < split_num; i++) { \ 3072 rs_t = (rs >> (bit_size * i)) & filter; \ 3073 rt_t = (rt >> (bit_size * i)) & filter; \ 3074 cc = (dsp >> (24 + i)) & 0x01; \ 3075 cc = cc == 1 ? rs_t : rt_t; \ 3076 \ 3077 result |= (target_ulong)cc << (bit_size * i); \ 3078 } \ 3079 \ 3080 if (ret32bit) { \ 3081 result = (target_long)(int32_t)(result & MIPSDSP_LLO); \ 3082 } \ 3083 \ 3084 return result; \ 3085 } 3086 3087 PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1); 3088 PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1); 3089 3090 #ifdef TARGET_MIPS64 3091 PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0); 3092 PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0); 3093 PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0); 3094 #endif 3095 #undef PICK_INSN 3096 3097 target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt) 3098 { 3099 uint32_t rsl, rth; 3100 3101 rsl = rs & MIPSDSP_LO; 3102 rth = (rt & MIPSDSP_HI) >> 16; 3103 3104 return (target_long)(int32_t)((rsl << 16) | rth); 3105 } 3106 3107 #if defined(TARGET_MIPS64) 3108 target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt) 3109 { 3110 uint32_t rs0, rt1; 3111 3112 rs0 = rs & MIPSDSP_LLO; 3113 rt1 = (rt >> 32) & MIPSDSP_LLO; 3114 3115 return ((uint64_t)rs0 << 32) | (uint64_t)rt1; 3116 } 3117 #endif 3118 3119 /** DSP Accumulator and DSPControl Access Sub-class insns **/ 3120 target_ulong helper_extr_w(target_ulong ac, target_ulong shift, 3121 CPUMIPSState *env) 3122 { 3123 int32_t tempI; 3124 int64_t tempDL[2]; 3125 3126 shift = shift & 0x1F; 3127 3128 mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); 3129 if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3130 (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3131 set_DSPControl_overflow_flag(1, 23, env); 3132 } 3133 3134 tempI = (tempDL[0] >> 1) & MIPSDSP_LLO; 3135 3136 tempDL[0] += 1; 3137 if (tempDL[0] == 0) { 3138 tempDL[1] += 1; 3139 } 3140 3141 if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3142 ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3143 set_DSPControl_overflow_flag(1, 23, env); 3144 } 3145 3146 return (target_long)tempI; 3147 } 3148 3149 target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift, 3150 CPUMIPSState *env) 3151 { 3152 int64_t tempDL[2]; 3153 3154 shift = shift & 0x1F; 3155 3156 mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); 3157 if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3158 (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3159 set_DSPControl_overflow_flag(1, 23, env); 3160 } 3161 3162 tempDL[0] += 1; 3163 if (tempDL[0] == 0) { 3164 tempDL[1] += 1; 3165 } 3166 3167 if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3168 ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3169 set_DSPControl_overflow_flag(1, 23, env); 3170 } 3171 3172 return (target_long)(int32_t)(tempDL[0] >> 1); 3173 } 3174 3175 target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift, 3176 CPUMIPSState *env) 3177 { 3178 int32_t tempI, temp64; 3179 int64_t tempDL[2]; 3180 3181 shift = shift & 0x1F; 3182 3183 mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env); 3184 if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3185 (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3186 set_DSPControl_overflow_flag(1, 23, env); 3187 } 3188 tempDL[0] += 1; 3189 if (tempDL[0] == 0) { 3190 tempDL[1] += 1; 3191 } 3192 tempI = tempDL[0] >> 1; 3193 3194 if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && 3195 ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) { 3196 temp64 = tempDL[1] & 0x01; 3197 if (temp64 == 0) { 3198 tempI = 0x7FFFFFFF; 3199 } else { 3200 tempI = 0x80000000; 3201 } 3202 set_DSPControl_overflow_flag(1, 23, env); 3203 } 3204 3205 return (target_long)tempI; 3206 } 3207 3208 #if defined(TARGET_MIPS64) 3209 target_ulong helper_dextr_w(target_ulong ac, target_ulong shift, 3210 CPUMIPSState *env) 3211 { 3212 uint64_t temp[3]; 3213 3214 shift = shift & 0x3F; 3215 3216 mipsdsp_rndrashift_acc(temp, ac, shift, env); 3217 3218 return (int64_t)(int32_t)(temp[0] >> 1); 3219 } 3220 3221 target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift, 3222 CPUMIPSState *env) 3223 { 3224 uint64_t temp[3]; 3225 uint32_t temp128; 3226 3227 shift = shift & 0x3F; 3228 mipsdsp_rndrashift_acc(temp, ac, shift, env); 3229 3230 temp[0] += 1; 3231 if (temp[0] == 0) { 3232 temp[1] += 1; 3233 if (temp[1] == 0) { 3234 temp[2] += 1; 3235 } 3236 } 3237 3238 temp128 = temp[2] & 0x01; 3239 3240 if ((temp128 != 0 || temp[1] != 0) && 3241 (temp128 != 1 || temp[1] != ~0ull)) { 3242 set_DSPControl_overflow_flag(1, 23, env); 3243 } 3244 3245 return (int64_t)(int32_t)(temp[0] >> 1); 3246 } 3247 3248 target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift, 3249 CPUMIPSState *env) 3250 { 3251 uint64_t temp[3]; 3252 uint32_t temp128; 3253 3254 shift = shift & 0x3F; 3255 mipsdsp_rndrashift_acc(temp, ac, shift, env); 3256 3257 temp[0] += 1; 3258 if (temp[0] == 0) { 3259 temp[1] += 1; 3260 if (temp[1] == 0) { 3261 temp[2] += 1; 3262 } 3263 } 3264 3265 temp128 = temp[2] & 0x01; 3266 3267 if ((temp128 != 0 || temp[1] != 0) && 3268 (temp128 != 1 || temp[1] != ~0ull)) { 3269 if (temp128 == 0) { 3270 temp[0] = 0x0FFFFFFFF; 3271 } else { 3272 temp[0] = 0x0100000000ULL; 3273 } 3274 set_DSPControl_overflow_flag(1, 23, env); 3275 } 3276 3277 return (int64_t)(int32_t)(temp[0] >> 1); 3278 } 3279 3280 target_ulong helper_dextr_l(target_ulong ac, target_ulong shift, 3281 CPUMIPSState *env) 3282 { 3283 uint64_t temp[3]; 3284 target_ulong ret; 3285 3286 shift = shift & 0x3F; 3287 3288 mipsdsp_rndrashift_acc(temp, ac, shift, env); 3289 3290 ret = (temp[1] << 63) | (temp[0] >> 1); 3291 3292 return ret; 3293 } 3294 3295 target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, 3296 CPUMIPSState *env) 3297 { 3298 uint64_t temp[3]; 3299 uint32_t temp128; 3300 target_ulong ret; 3301 3302 shift = shift & 0x3F; 3303 mipsdsp_rndrashift_acc(temp, ac, shift, env); 3304 3305 temp[0] += 1; 3306 if (temp[0] == 0) { 3307 temp[1] += 1; 3308 if (temp[1] == 0) { 3309 temp[2] += 1; 3310 } 3311 } 3312 3313 temp128 = temp[2] & 0x01; 3314 3315 if ((temp128 != 0 || temp[1] != 0) && 3316 (temp128 != 1 || temp[1] != ~0ull)) { 3317 set_DSPControl_overflow_flag(1, 23, env); 3318 } 3319 3320 ret = (temp[1] << 63) | (temp[0] >> 1); 3321 3322 return ret; 3323 } 3324 3325 target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, 3326 CPUMIPSState *env) 3327 { 3328 uint64_t temp[3]; 3329 uint32_t temp128; 3330 target_ulong ret; 3331 3332 shift = shift & 0x3F; 3333 mipsdsp_rndrashift_acc(temp, ac, shift, env); 3334 3335 temp[0] += 1; 3336 if (temp[0] == 0) { 3337 temp[1] += 1; 3338 if (temp[1] == 0) { 3339 temp[2] += 1; 3340 } 3341 } 3342 3343 temp128 = temp[2] & 0x01; 3344 3345 if ((temp128 != 0 || temp[1] != 0) && 3346 (temp128 != 1 || temp[1] != ~0ull)) { 3347 if (temp128 == 0) { 3348 temp[1] &= ~0x00ull - 1; 3349 temp[0] |= ~0x00ull - 1; 3350 } else { 3351 temp[1] |= 0x01; 3352 temp[0] &= 0x01; 3353 } 3354 set_DSPControl_overflow_flag(1, 23, env); 3355 } 3356 3357 ret = (temp[1] << 63) | (temp[0] >> 1); 3358 3359 return ret; 3360 } 3361 #endif 3362 3363 target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift, 3364 CPUMIPSState *env) 3365 { 3366 int64_t temp, acc; 3367 3368 shift = shift & 0x1F; 3369 3370 acc = ((int64_t)env->active_tc.HI[ac] << 32) | 3371 ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF); 3372 3373 temp = acc >> shift; 3374 3375 if (temp > (int64_t)0x7FFF) { 3376 temp = 0x00007FFF; 3377 set_DSPControl_overflow_flag(1, 23, env); 3378 } else if (temp < (int64_t)0xFFFFFFFFFFFF8000ULL) { 3379 temp = 0xFFFF8000; 3380 set_DSPControl_overflow_flag(1, 23, env); 3381 } 3382 3383 return (target_long)(int32_t)(temp & 0xFFFFFFFF); 3384 } 3385 3386 3387 #if defined(TARGET_MIPS64) 3388 target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift, 3389 CPUMIPSState *env) 3390 { 3391 int64_t temp[2]; 3392 uint32_t temp127; 3393 3394 shift = shift & 0x1F; 3395 3396 mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env); 3397 3398 temp127 = (temp[1] >> 63) & 0x01; 3399 3400 if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) { 3401 temp[0] &= 0xFFFF0000; 3402 temp[0] |= 0x00007FFF; 3403 set_DSPControl_overflow_flag(1, 23, env); 3404 } else if ((temp127 == 1) && 3405 (temp[1] < 0xFFFFFFFFFFFFFFFFll 3406 || temp[0] < 0xFFFFFFFFFFFF1000ll)) { 3407 temp[0] &= 0xFFFF0000; 3408 temp[0] |= 0x00008000; 3409 set_DSPControl_overflow_flag(1, 23, env); 3410 } 3411 3412 return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO); 3413 } 3414 3415 #endif 3416 3417 target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env) 3418 { 3419 int32_t start_pos; 3420 int sub; 3421 uint32_t temp; 3422 uint64_t acc; 3423 3424 size = size & 0x1F; 3425 3426 temp = 0; 3427 start_pos = get_DSPControl_pos(env); 3428 sub = start_pos - (size + 1); 3429 if (sub >= -1) { 3430 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | 3431 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); 3432 temp = (acc >> (start_pos - size)) & (~0U >> (31 - size)); 3433 set_DSPControl_efi(0, env); 3434 } else { 3435 set_DSPControl_efi(1, env); 3436 } 3437 3438 return (target_ulong)temp; 3439 } 3440 3441 target_ulong helper_extpdp(target_ulong ac, target_ulong size, 3442 CPUMIPSState *env) 3443 { 3444 int32_t start_pos; 3445 int sub; 3446 uint32_t temp; 3447 uint64_t acc; 3448 3449 size = size & 0x1F; 3450 temp = 0; 3451 start_pos = get_DSPControl_pos(env); 3452 sub = start_pos - (size + 1); 3453 if (sub >= -1) { 3454 acc = ((uint64_t)env->active_tc.HI[ac] << 32) | 3455 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); 3456 temp = extract64(acc, start_pos - size, size + 1); 3457 3458 set_DSPControl_pos(sub, env); 3459 set_DSPControl_efi(0, env); 3460 } else { 3461 set_DSPControl_efi(1, env); 3462 } 3463 3464 return (target_ulong)temp; 3465 } 3466 3467 3468 #if defined(TARGET_MIPS64) 3469 target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env) 3470 { 3471 int start_pos; 3472 int len; 3473 int sub; 3474 uint64_t tempB, tempA; 3475 uint64_t temp; 3476 3477 temp = 0; 3478 3479 size = size & 0x3F; 3480 start_pos = get_DSPControl_pos(env); 3481 len = start_pos - size; 3482 tempB = env->active_tc.HI[ac]; 3483 tempA = env->active_tc.LO[ac]; 3484 3485 sub = start_pos - (size + 1); 3486 3487 if (sub >= -1) { 3488 temp = (tempB << (64 - len)) | (tempA >> len); 3489 temp = temp & ((1ULL << (size + 1)) - 1); 3490 set_DSPControl_efi(0, env); 3491 } else { 3492 set_DSPControl_efi(1, env); 3493 } 3494 3495 return temp; 3496 } 3497 3498 target_ulong helper_dextpdp(target_ulong ac, target_ulong size, 3499 CPUMIPSState *env) 3500 { 3501 int start_pos; 3502 int len; 3503 int sub; 3504 uint64_t tempB, tempA; 3505 uint64_t temp; 3506 3507 temp = 0; 3508 size = size & 0x3F; 3509 start_pos = get_DSPControl_pos(env); 3510 len = start_pos - size; 3511 tempB = env->active_tc.HI[ac]; 3512 tempA = env->active_tc.LO[ac]; 3513 3514 sub = start_pos - (size + 1); 3515 3516 if (sub >= -1) { 3517 temp = (tempB << (64 - len)) | (tempA >> len); 3518 temp = temp & ((1ULL << (size + 1)) - 1); 3519 set_DSPControl_pos(sub, env); 3520 set_DSPControl_efi(0, env); 3521 } else { 3522 set_DSPControl_efi(1, env); 3523 } 3524 3525 return temp; 3526 } 3527 3528 #endif 3529 3530 void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env) 3531 { 3532 int8_t rs5_0; 3533 uint64_t temp, acc; 3534 3535 rs5_0 = rs & 0x3F; 3536 rs5_0 = (int8_t)(rs5_0 << 2) >> 2; 3537 3538 if (unlikely(rs5_0 == 0)) { 3539 return; 3540 } 3541 3542 acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) | 3543 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); 3544 3545 if (rs5_0 > 0) { 3546 temp = acc >> rs5_0; 3547 } else { 3548 temp = acc << -rs5_0; 3549 } 3550 3551 env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32); 3552 env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO); 3553 } 3554 3555 #if defined(TARGET_MIPS64) 3556 void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env) 3557 { 3558 int8_t shift_t; 3559 uint64_t tempB, tempA; 3560 3561 shift_t = (int8_t)(shift << 1) >> 1; 3562 3563 tempB = env->active_tc.HI[ac]; 3564 tempA = env->active_tc.LO[ac]; 3565 3566 if (shift_t != 0) { 3567 if (shift_t >= 0) { 3568 tempA = (tempB << (64 - shift_t)) | (tempA >> shift_t); 3569 tempB = tempB >> shift_t; 3570 } else { 3571 shift_t = -shift_t; 3572 tempB = (tempB << shift_t) | (tempA >> (64 - shift_t)); 3573 tempA = tempA << shift_t; 3574 } 3575 } 3576 3577 env->active_tc.HI[ac] = tempB; 3578 env->active_tc.LO[ac] = tempA; 3579 } 3580 3581 #endif 3582 void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env) 3583 { 3584 int32_t tempA, tempB, pos; 3585 3586 tempA = rs; 3587 tempB = env->active_tc.LO[ac]; 3588 env->active_tc.HI[ac] = (target_long)tempB; 3589 env->active_tc.LO[ac] = (target_long)tempA; 3590 pos = get_DSPControl_pos(env); 3591 3592 if (pos > 32) { 3593 return; 3594 } else { 3595 set_DSPControl_pos(pos + 32, env); 3596 } 3597 } 3598 3599 #if defined(TARGET_MIPS64) 3600 void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env) 3601 { 3602 uint8_t ac_t; 3603 uint8_t pos; 3604 uint64_t tempB, tempA; 3605 3606 ac_t = ac & 0x3; 3607 3608 tempA = rs; 3609 tempB = env->active_tc.LO[ac_t]; 3610 3611 env->active_tc.HI[ac_t] = tempB; 3612 env->active_tc.LO[ac_t] = tempA; 3613 3614 pos = get_DSPControl_pos(env); 3615 3616 if (pos <= 64) { 3617 pos = pos + 64; 3618 set_DSPControl_pos(pos, env); 3619 } 3620 } 3621 #endif 3622 3623 void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env) 3624 { 3625 uint8_t mask[6]; 3626 uint8_t i; 3627 uint32_t newbits, overwrite; 3628 target_ulong dsp; 3629 3630 newbits = 0x00; 3631 overwrite = 0xFFFFFFFF; 3632 dsp = env->active_tc.DSPControl; 3633 3634 for (i = 0; i < 6; i++) { 3635 mask[i] = (mask_num >> i) & 0x01; 3636 } 3637 3638 if (mask[0] == 1) { 3639 #if defined(TARGET_MIPS64) 3640 overwrite &= 0xFFFFFF80; 3641 newbits &= 0xFFFFFF80; 3642 newbits |= 0x0000007F & rs; 3643 #else 3644 overwrite &= 0xFFFFFFC0; 3645 newbits &= 0xFFFFFFC0; 3646 newbits |= 0x0000003F & rs; 3647 #endif 3648 } 3649 3650 if (mask[1] == 1) { 3651 overwrite &= 0xFFFFE07F; 3652 newbits &= 0xFFFFE07F; 3653 newbits |= 0x00001F80 & rs; 3654 } 3655 3656 if (mask[2] == 1) { 3657 overwrite &= 0xFFFFDFFF; 3658 newbits &= 0xFFFFDFFF; 3659 newbits |= 0x00002000 & rs; 3660 } 3661 3662 if (mask[3] == 1) { 3663 overwrite &= 0xFF00FFFF; 3664 newbits &= 0xFF00FFFF; 3665 newbits |= 0x00FF0000 & rs; 3666 } 3667 3668 if (mask[4] == 1) { 3669 overwrite &= 0x00FFFFFF; 3670 newbits &= 0x00FFFFFF; 3671 #if defined(TARGET_MIPS64) 3672 newbits |= 0xFF000000 & rs; 3673 #else 3674 newbits |= 0x0F000000 & rs; 3675 #endif 3676 } 3677 3678 if (mask[5] == 1) { 3679 overwrite &= 0xFFFFBFFF; 3680 newbits &= 0xFFFFBFFF; 3681 newbits |= 0x00004000 & rs; 3682 } 3683 3684 dsp = dsp & overwrite; 3685 dsp = dsp | newbits; 3686 env->active_tc.DSPControl = dsp; 3687 } 3688 3689 void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env) 3690 { 3691 cpu_wrdsp(rs, mask_num, env); 3692 } 3693 3694 uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env) 3695 { 3696 uint8_t mask[6]; 3697 uint32_t ruler, i; 3698 target_ulong temp; 3699 target_ulong dsp; 3700 3701 ruler = 0x01; 3702 for (i = 0; i < 6; i++) { 3703 mask[i] = (mask_num & ruler) >> i ; 3704 ruler = ruler << 1; 3705 } 3706 3707 temp = 0x00; 3708 dsp = env->active_tc.DSPControl; 3709 3710 if (mask[0] == 1) { 3711 #if defined(TARGET_MIPS64) 3712 temp |= dsp & 0x7F; 3713 #else 3714 temp |= dsp & 0x3F; 3715 #endif 3716 } 3717 3718 if (mask[1] == 1) { 3719 temp |= dsp & 0x1F80; 3720 } 3721 3722 if (mask[2] == 1) { 3723 temp |= dsp & 0x2000; 3724 } 3725 3726 if (mask[3] == 1) { 3727 temp |= dsp & 0x00FF0000; 3728 } 3729 3730 if (mask[4] == 1) { 3731 #if defined(TARGET_MIPS64) 3732 temp |= dsp & 0xFF000000; 3733 #else 3734 temp |= dsp & 0x0F000000; 3735 #endif 3736 } 3737 3738 if (mask[5] == 1) { 3739 temp |= dsp & 0x4000; 3740 } 3741 3742 return temp; 3743 } 3744 3745 target_ulong helper_rddsp(target_ulong mask_num, CPUMIPSState *env) 3746 { 3747 return cpu_rddsp(mask_num, env); 3748 } 3749 3750 3751 #undef MIPSDSP_LHI 3752 #undef MIPSDSP_LLO 3753 #undef MIPSDSP_HI 3754 #undef MIPSDSP_LO 3755 #undef MIPSDSP_Q3 3756 #undef MIPSDSP_Q2 3757 #undef MIPSDSP_Q1 3758 #undef MIPSDSP_Q0 3759 3760 #undef MIPSDSP_SPLIT32_8 3761 #undef MIPSDSP_SPLIT32_16 3762 3763 #undef MIPSDSP_RETURN32_8 3764 #undef MIPSDSP_RETURN32_16 3765 3766 #ifdef TARGET_MIPS64 3767 #undef MIPSDSP_SPLIT64_16 3768 #undef MIPSDSP_SPLIT64_32 3769 #undef MIPSDSP_RETURN64_16 3770 #undef MIPSDSP_RETURN64_32 3771 #endif 3772