dsp_helper.c (138436B)
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 */ 29typedef 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 38typedef 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 54static 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 60static 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 66static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env) 67{ 68 return (env->active_tc.DSPControl >> 13) & 0x01; 69} 70 71static 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 82static 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 97static 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 113static 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) \ 120static 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} 130DO_MIPS_SAT_ABS(8) 131DO_MIPS_SAT_ABS(16) 132DO_MIPS_SAT_ABS(32) 133#undef DO_MIPS_SAT_ABS 134 135/* get sum value */ 136static 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 149static 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 168static 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 187static 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 200static 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 214static 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 231static 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 248static 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. */ 282static 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 309static 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 336static 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 351static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b) 352{ 353 return a * b; 354} 355 356#ifdef TARGET_MIPS64 357static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b) 358{ 359 return a * b; 360} 361#endif 362 363static 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 382static 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 */ 398static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov) 399{ 400 return a >> mov; 401} 402 403static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov) 404{ 405 return a >> mov; 406} 407 408static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov) 409{ 410 return a >> mov; 411} 412 413static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov) 414{ 415 return a >> mov; 416} 417 418#ifdef TARGET_MIPS64 419static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov) 420{ 421 return a >> mov; 422} 423#endif 424 425static 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 */ 435static 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 445static 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 454static 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 464static 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 473static 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 483static 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 492static 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. */ 503static 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 */ 518static 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.*/ 539static 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 566static 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 581static 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 596static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b) 597{ 598 return (uint16_t)a * (uint16_t)b; 599} 600 601static 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 616static 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 622static 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 638static 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 654static 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 675static 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 697static 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 711static 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 727static 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 745static 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 771static 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 797static 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 810static 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 823static 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 837static 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 849static 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 867static 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 885static 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 894static 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 904static 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 913static 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 923static 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 937static 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 954static 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 968static 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 984static 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 996static 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 1010static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b) 1011{ 1012 return a == b; 1013} 1014 1015static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b) 1016{ 1017 return a <= b; 1018} 1019 1020static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b) 1021{ 1022 return a < b; 1023} 1024 1025static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b) 1026{ 1027 return a == b; 1028} 1029 1030static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b) 1031{ 1032 return a <= b; 1033} 1034 1035static 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) \ 1097target_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} 1110MIPSDSP32_UNOP_ENV(absq_s_ph, sat_abs16, sh) 1111MIPSDSP32_UNOP_ENV(absq_s_qb, sat_abs8, sb) 1112MIPSDSP32_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) \ 1117target_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} 1130MIPSDSP64_UNOP_ENV(absq_s_ob, sat_abs8, sb) 1131MIPSDSP64_UNOP_ENV(absq_s_qh, sat_abs16, sh) 1132MIPSDSP64_UNOP_ENV(absq_s_pw, sat_abs32, sw) 1133#undef MIPSDSP64_UNOP_ENV 1134#endif 1135 1136#define MIPSDSP32_BINOP(name, func, element) \ 1137target_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} 1151MIPSDSP32_BINOP(addqh_ph, rshift1_add_q16, sh); 1152MIPSDSP32_BINOP(addqh_r_ph, rrshift1_add_q16, sh); 1153MIPSDSP32_BINOP(addqh_r_w, rrshift1_add_q32, sw); 1154MIPSDSP32_BINOP(addqh_w, rshift1_add_q32, sw); 1155MIPSDSP32_BINOP(adduh_qb, rshift1_add_u8, ub); 1156MIPSDSP32_BINOP(adduh_r_qb, rrshift1_add_u8, ub); 1157MIPSDSP32_BINOP(subqh_ph, rshift1_sub_q16, sh); 1158MIPSDSP32_BINOP(subqh_r_ph, rrshift1_sub_q16, sh); 1159MIPSDSP32_BINOP(subqh_r_w, rrshift1_sub_q32, sw); 1160MIPSDSP32_BINOP(subqh_w, rshift1_sub_q32, sw); 1161#undef MIPSDSP32_BINOP 1162 1163#define MIPSDSP32_BINOP_ENV(name, func, element) \ 1164target_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} 1179MIPSDSP32_BINOP_ENV(addq_ph, add_i16, sh) 1180MIPSDSP32_BINOP_ENV(addq_s_ph, sat_add_i16, sh) 1181MIPSDSP32_BINOP_ENV(addq_s_w, sat_add_i32, sw); 1182MIPSDSP32_BINOP_ENV(addu_ph, add_u16, sh) 1183MIPSDSP32_BINOP_ENV(addu_qb, add_u8, ub); 1184MIPSDSP32_BINOP_ENV(addu_s_ph, sat_add_u16, sh) 1185MIPSDSP32_BINOP_ENV(addu_s_qb, sat_add_u8, ub); 1186MIPSDSP32_BINOP_ENV(subq_ph, sub_i16, sh); 1187MIPSDSP32_BINOP_ENV(subq_s_ph, sat16_sub, sh); 1188MIPSDSP32_BINOP_ENV(subq_s_w, sat32_sub, sw); 1189MIPSDSP32_BINOP_ENV(subu_ph, sub_u16_u16, sh); 1190MIPSDSP32_BINOP_ENV(subu_qb, sub_u8, ub); 1191MIPSDSP32_BINOP_ENV(subu_s_ph, satu16_sub_u16_u16, sh); 1192MIPSDSP32_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) \ 1197target_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} 1211MIPSDSP64_BINOP(adduh_ob, rshift1_add_u8, ub); 1212MIPSDSP64_BINOP(adduh_r_ob, rrshift1_add_u8, ub); 1213MIPSDSP64_BINOP(subuh_ob, rshift1_sub_u8, ub); 1214MIPSDSP64_BINOP(subuh_r_ob, rrshift1_sub_u8, ub); 1215#undef MIPSDSP64_BINOP 1216 1217#define MIPSDSP64_BINOP_ENV(name, func, element) \ 1218target_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} 1233MIPSDSP64_BINOP_ENV(addq_pw, add_i32, sw); 1234MIPSDSP64_BINOP_ENV(addq_qh, add_i16, sh); 1235MIPSDSP64_BINOP_ENV(addq_s_pw, sat_add_i32, sw); 1236MIPSDSP64_BINOP_ENV(addq_s_qh, sat_add_i16, sh); 1237MIPSDSP64_BINOP_ENV(addu_ob, add_u8, uh); 1238MIPSDSP64_BINOP_ENV(addu_qh, add_u16, uh); 1239MIPSDSP64_BINOP_ENV(addu_s_ob, sat_add_u8, uh); 1240MIPSDSP64_BINOP_ENV(addu_s_qh, sat_add_u16, uh); 1241MIPSDSP64_BINOP_ENV(subq_pw, sub32, sw); 1242MIPSDSP64_BINOP_ENV(subq_qh, sub_i16, sh); 1243MIPSDSP64_BINOP_ENV(subq_s_pw, sat32_sub, sw); 1244MIPSDSP64_BINOP_ENV(subq_s_qh, sat16_sub, sh); 1245MIPSDSP64_BINOP_ENV(subu_ob, sub_u8, uh); 1246MIPSDSP64_BINOP_ENV(subu_qh, sub_u16_u16, uh); 1247MIPSDSP64_BINOP_ENV(subu_s_ob, satu8_sub, uh); 1248MIPSDSP64_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) \ 1254target_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 1272SUBUH_QB(subuh, 0); 1273SUBUH_QB(subuh_r, 1); 1274 1275#undef SUBUH_QB 1276 1277target_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 1292target_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 1312target_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 1330target_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) 1344target_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)\ 1359target_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 1371PRECR_QB_PH(precr, 16, 0); 1372PRECR_QB_PH(precrq, 24, 8); 1373 1374#undef PRECR_QB_OH 1375 1376target_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 1387target_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 1405target_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 1415target_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) 1427target_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) \ 1456target_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 1482PRECR_QH_PW(sra, 0); 1483PRECR_QH_PW(sra_r, 1); 1484 1485#undef PRECR_QH_PW 1486 1487target_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 1510target_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 1522target_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 1542target_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 1553target_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) 1573target_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) \ 1604target_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 1618PRECEQ_PW(qhl, 48, 32); 1619PRECEQ_PW(qhr, 16, 0); 1620PRECEQ_PW(qhla, 48, 16); 1621PRECEQ_PW(qhra, 32, 0); 1622 1623#undef PRECEQ_PW 1624 1625#endif 1626 1627#define PRECEQU_PH(name, a, b) \ 1628target_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 1641PRECEQU_PH(qbl, 24, 16); 1642PRECEQU_PH(qbr, 8, 0); 1643PRECEQU_PH(qbla, 24, 8); 1644PRECEQU_PH(qbra, 16, 0); 1645 1646#undef PRECEQU_PH 1647 1648#if defined(TARGET_MIPS64) 1649#define PRECEQU_QH(name, a, b, c, d) \ 1650target_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 1667PRECEQU_QH(obl, 56, 48, 40, 32); 1668PRECEQU_QH(obr, 24, 16, 8, 0); 1669PRECEQU_QH(obla, 56, 40, 24, 8); 1670PRECEQU_QH(obra, 48, 32, 16, 0); 1671 1672#undef PRECEQU_QH 1673 1674#endif 1675 1676#define PRECEU_PH(name, a, b) \ 1677target_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 1687PRECEU_PH(qbl, 24, 16); 1688PRECEU_PH(qbr, 8, 0); 1689PRECEU_PH(qbla, 24, 8); 1690PRECEU_PH(qbra, 16, 0); 1691 1692#undef PRECEU_PH 1693 1694#if defined(TARGET_MIPS64) 1695#define PRECEU_QH(name, a, b, c, d) \ 1696target_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 1708PRECEU_QH(obl, 56, 48, 40, 32); 1709PRECEU_QH(obr, 24, 16, 8, 0); 1710PRECEU_QH(obla, 56, 40, 24, 8); 1711PRECEU_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) \ 1719target_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) \ 1736target_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 1753SHIFT_QB_ENV(shll, lshift8); 1754SHIFT_QB(shrl, rshift_u8); 1755 1756SHIFT_QB(shra, rashift8); 1757SHIFT_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) \ 1764target_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) \ 1783target_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 1802SHIFT_OB_ENV(shll, lshift8); 1803SHIFT_OB(shrl, rshift_u8); 1804 1805SHIFT_OB(shra, rashift8); 1806SHIFT_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) \ 1814target_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 1829SHIFT_PH(shll, lshift16); 1830SHIFT_PH(shll_s, sat16_lshift); 1831 1832#undef SHIFT_PH 1833 1834#if defined(TARGET_MIPS64) 1835#define SHIFT_QH(name, func) \ 1836target_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) \ 1853target_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 1870SHIFT_QH_ENV(shll, lshift16); 1871SHIFT_QH_ENV(shll_s, sat16_lshift); 1872 1873SHIFT_QH(shrl, rshift_u16); 1874SHIFT_QH(shra, rashift16); 1875SHIFT_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) \ 1883target_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) \ 1894target_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 1905SHIFT_W_ENV(shll_s, sat32_lshift); 1906SHIFT_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) \ 1913target_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) \ 1927target_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 1941SHIFT_PW_ENV(shll, lshift32); 1942SHIFT_PW_ENV(shll_s, sat32_lshift); 1943 1944SHIFT_PW(shra, rashift32); 1945SHIFT_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) \ 1953target_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 1967SHIFT_PH(shrl, rshift_u16); 1968SHIFT_PH(shra, rashift16); 1969SHIFT_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) \ 1981target_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 1997MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \ 1998 24, 16, MIPSDSP_Q0, \ 1999 16, 0, MIPSDSP_LO); 2000MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \ 2001 8, 0, MIPSDSP_Q0, \ 2002 16, 0, MIPSDSP_LO); 2003MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \ 2004 16, 0, MIPSDSP_LO, \ 2005 16, 0, MIPSDSP_LO); 2006MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \ 2007 16, 0, MIPSDSP_LO, \ 2008 16, 0, MIPSDSP_LO); 2009MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \ 2010 16, 0, MIPSDSP_LO, \ 2011 16, 0, MIPSDSP_LO); 2012MUL_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) \ 2019target_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 2032MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16); 2033MUL_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) \ 2038void 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 2065MUL_VOID_PH(mulsaq_s_w_ph, 1); 2066MUL_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) \ 2074target_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 2098MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \ 2099 56, 48, 40, 32, MIPSDSP_Q0, \ 2100 48, 32, 16, 0, MIPSDSP_LO); 2101MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \ 2102 24, 16, 8, 0, MIPSDSP_Q0, \ 2103 48, 32, 16, 0, MIPSDSP_LO); 2104MUL_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) \ 2113target_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 2131MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32); 2132MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0); 2133 2134#undef MUL_RETURN64_32_QH 2135 2136void 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) \ 2180void 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 2210DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16); 2211DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0); 2212DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16); 2213DP_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) \ 2221void 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 2275DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32); 2276DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0); 2277DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32); 2278DP_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) \ 2284void 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 2312DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0); 2313DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16); 2314DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0); 2315DP_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) \ 2319void 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 2350DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0); 2351DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16); 2352DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0); 2353DP_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) \ 2358void 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 2398DP_128OPERATION_PH(dpaqx_sa_w_ph, 1); 2399DP_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) \ 2405void 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 2463DP_QH(dpa_w_qh, 1, 0); 2464DP_QH(dpaq_s_w_qh, 1, 1); 2465DP_QH(dps_w_qh, 0, 0); 2466DP_QH(dpsq_s_w_qh, 0, 1); 2467 2468#undef DP_QH 2469 2470#endif 2471 2472#define DP_L_W(name, is_add) \ 2473void 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 2511DP_L_W(dpaq_sa_l_w, 1); 2512DP_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) \ 2518void 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 2563DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63); 2564DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63); 2565 2566#undef DP_L_PW 2567 2568void 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) \ 2628void 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 2647MAQ_S_W(maq_s_w_phl, 16); 2648MAQ_S_W(maq_s_w_phr, 0); 2649 2650#undef MAQ_S_W 2651 2652#define MAQ_SA_W(name, mov) \ 2653void 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 2670MAQ_SA_W(maq_sa_w_phl, 16); 2671MAQ_SA_W(maq_sa_w_phr, 0); 2672 2673#undef MAQ_SA_W 2674 2675#define MULQ_W(name, addvar) \ 2676target_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 2698MULQ_W(mulq_s_w, 0); 2699MULQ_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) \ 2706void 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 2744MAQ_S_W_QH(maq_s_w_qhll, 48); 2745MAQ_S_W_QH(maq_s_w_qhlr, 32); 2746MAQ_S_W_QH(maq_s_w_qhrl, 16); 2747MAQ_S_W_QH(maq_s_w_qhrr, 0); 2748 2749#undef MAQ_S_W_QH 2750 2751#define MAQ_SA_W(name, mov) \ 2752void 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 2775MAQ_SA_W(maq_sa_w_qhll, 48); 2776MAQ_SA_W(maq_sa_w_qhlr, 32); 2777MAQ_SA_W(maq_sa_w_qhrl, 16); 2778MAQ_SA_W(maq_sa_w_qhrr, 0); 2779 2780#undef MAQ_SA_W 2781 2782#define MAQ_S_L_PW(name, mov) \ 2783void 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 2819MAQ_S_L_PW(maq_s_l_pwl, 32); 2820MAQ_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) \ 2825void 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 2895DM_OPERATE(dmadd, mul_i32_i32, 1, 1); 2896DM_OPERATE(dmaddu, mul_u32_u32, 1, 0); 2897DM_OPERATE(dmsub, mul_i32_i32, 0, 1); 2898DM_OPERATE(dmsubu, mul_u32_u32, 0, 0); 2899#undef DM_OPERATE 2900#endif 2901 2902/** DSP Bit/Manipulation Sub-class insns **/ 2903target_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) \ 2920target_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 2945BIT_INSV(insv, 0x1F, int32_t); 2946#ifdef TARGET_MIPS64 2947BIT_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) \ 2955target_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 2972CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); 2973CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); 2974CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); 2975 2976#ifdef TARGET_MIPS64 2977CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); 2978CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); 2979CMP_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) \ 2986void 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 3005CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8); 3006CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8); 3007CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8); 3008 3009CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16); 3010CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16); 3011CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16); 3012 3013#ifdef TARGET_MIPS64 3014CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8); 3015CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8); 3016CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8); 3017 3018CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16); 3019CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16); 3020CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16); 3021 3022CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32); 3023CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32); 3024CMP_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) \ 3031target_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 3054CMPGDU_OB(eq) 3055CMPGDU_OB(lt) 3056CMPGDU_OB(le) 3057#undef CMPGDU_OB 3058#endif 3059 3060#define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \ 3061target_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 3087PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1); 3088PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1); 3089 3090#ifdef TARGET_MIPS64 3091PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0); 3092PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0); 3093PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0); 3094#endif 3095#undef PICK_INSN 3096 3097target_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) 3108target_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 **/ 3120target_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 3149target_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 3175target_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) 3209target_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 3221target_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 3248target_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 3280target_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 3295target_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 3325target_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 3363target_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) 3388target_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 3417target_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 3441target_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) 3469target_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 3498target_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 3530void 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) 3556void 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 3582void 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) 3600void 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 3623void 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 3689void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env) 3690{ 3691 cpu_wrdsp(rs, mask_num, env); 3692} 3693 3694uint32_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 3745target_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