dsp.cc revision 8794:e2ac2b7164dd
1/* 2 * Copyright (c) 2007 MIPS Technologies, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Brett Miller 29 */ 30 31#include "arch/mips/dsp.hh" 32#include "arch/mips/isa_traits.hh" 33#include "base/bitfield.hh" 34#include "base/misc.hh" 35#include "cpu/static_inst.hh" 36#include "sim/serialize.hh" 37 38using namespace MipsISA; 39using namespace std; 40 41int32_t 42MipsISA::bitrev(int32_t value) 43{ 44 int32_t result = 0; 45 int shift; 46 47 for (int i = 0; i < 16; i++) { 48 shift = 2 * i - 15; 49 50 if (shift < 0) 51 result |= (value & 1 << i) << -shift; 52 else 53 result |= (value & 1 << i) >> shift; 54 } 55 56 return result; 57} 58 59uint64_t 60MipsISA::dspSaturate(uint64_t value, int32_t fmt, int32_t sign, 61 uint32_t *overflow) 62{ 63 int64_t svalue = (int64_t)value; 64 65 switch (sign) { 66 case SIGNED: 67 if (svalue > (int64_t)FIXED_SMAX[fmt]) { 68 *overflow = 1; 69 svalue = (int64_t)FIXED_SMAX[fmt]; 70 } else if (svalue < (int64_t)FIXED_SMIN[fmt]) { 71 *overflow = 1; 72 svalue = (int64_t)FIXED_SMIN[fmt]; 73 } 74 break; 75 case UNSIGNED: 76 if (svalue > (int64_t)FIXED_UMAX[fmt]) { 77 *overflow = 1; 78 svalue = FIXED_UMAX[fmt]; 79 } else if (svalue < (int64_t)FIXED_UMIN[fmt]) { 80 *overflow = 1; 81 svalue = FIXED_UMIN[fmt]; 82 } 83 break; 84 } 85 86 return (uint64_t)svalue; 87} 88 89uint64_t 90MipsISA::checkOverflow(uint64_t value, int32_t fmt, int32_t sign, 91 uint32_t *overflow) 92{ 93 int64_t svalue = (int64_t)value; 94 95 switch (sign) 96 { 97 case SIGNED: 98 if (svalue > (int64_t)FIXED_SMAX[fmt] || 99 svalue < (int64_t)FIXED_SMIN[fmt]) 100 *overflow = 1; 101 break; 102 case UNSIGNED: 103 if (svalue > (int64_t)FIXED_UMAX[fmt] || 104 svalue < (int64_t)FIXED_UMIN[fmt]) 105 *overflow = 1; 106 break; 107 } 108 109 return (uint64_t)svalue; 110} 111 112uint64_t 113MipsISA::signExtend(uint64_t value, int32_t fmt) 114{ 115 int32_t signpos = SIMD_NBITS[fmt]; 116 uint64_t sign = uint64_t(1) << (signpos - 1); 117 uint64_t ones = ~(0ULL); 118 119 if (value & sign) 120 value |= (ones << signpos); // extend with ones 121 else 122 value &= (ones >> (64 - signpos)); // extend with zeros 123 124 return value; 125} 126 127uint64_t 128MipsISA::addHalfLsb(uint64_t value, int32_t lsbpos) 129{ 130 return value += ULL(1) << (lsbpos - 1); 131} 132 133int32_t 134MipsISA::dspAbs(int32_t a, int32_t fmt, uint32_t *dspctl) 135{ 136 int nvals = SIMD_NVALS[fmt]; 137 int32_t result; 138 int64_t svalue; 139 uint32_t ouflag = 0; 140 uint64_t a_values[SIMD_MAX_VALS]; 141 142 simdUnpack(a, a_values, fmt, SIGNED); 143 144 for (int i = 0; i < nvals; i++) { 145 svalue = (int64_t)a_values[i]; 146 147 if (a_values[i] == FIXED_SMIN[fmt]) { 148 a_values[i] = FIXED_SMAX[fmt]; 149 ouflag = 1; 150 } else if (svalue < 0) { 151 a_values[i] = uint64_t(0 - svalue); 152 } 153 } 154 155 simdPack(a_values, &result, fmt); 156 157 if (ouflag) 158 writeDSPControl(dspctl, (ouflag << 4) << DSP_CTL_POS[DSP_OUFLAG], 159 1 << DSP_OUFLAG); 160 161 return result; 162} 163 164int32_t 165MipsISA::dspAdd(int32_t a, int32_t b, int32_t fmt, int32_t saturate, 166 int32_t sign, uint32_t *dspctl) 167{ 168 int nvals = SIMD_NVALS[fmt]; 169 int32_t result; 170 uint32_t ouflag = 0; 171 uint64_t a_values[SIMD_MAX_VALS]; 172 uint64_t b_values[SIMD_MAX_VALS]; 173 174 simdUnpack(a, a_values, fmt, sign); 175 simdUnpack(b, b_values, fmt, sign); 176 177 for (int i = 0; i < nvals; i++) 178 { 179 if (saturate) 180 a_values[i] = dspSaturate(a_values[i] + b_values[i], fmt, sign, 181 &ouflag); 182 else 183 a_values[i] = checkOverflow(a_values[i] + b_values[i], fmt, sign, 184 &ouflag); 185 } 186 187 simdPack(a_values, &result, fmt); 188 189 if (ouflag) 190 writeDSPControl(dspctl, (ouflag << 4) << DSP_CTL_POS[DSP_OUFLAG], 191 1 << DSP_OUFLAG); 192 193 return result; 194} 195 196int32_t 197MipsISA::dspAddh(int32_t a, int32_t b, int32_t fmt, int32_t round, 198 int32_t sign) 199{ 200 int nvals = SIMD_NVALS[fmt]; 201 int32_t result; 202 uint64_t a_values[SIMD_MAX_VALS]; 203 uint64_t b_values[SIMD_MAX_VALS]; 204 205 simdUnpack(a, a_values, fmt, sign); 206 simdUnpack(b, b_values, fmt, sign); 207 208 for (int i = 0; i < nvals; i++) { 209 if (round) 210 a_values[i] = addHalfLsb(a_values[i] + b_values[i], 1) >> 1; 211 else 212 a_values[i] = (a_values[i] + b_values[i]) >> 1; 213 } 214 215 simdPack(a_values, &result, fmt); 216 217 return result; 218} 219 220int32_t 221MipsISA::dspSub(int32_t a, int32_t b, int32_t fmt, int32_t saturate, 222 int32_t sign, uint32_t *dspctl) 223{ 224 int nvals = SIMD_NVALS[fmt]; 225 int32_t result; 226 uint32_t ouflag = 0; 227 uint64_t a_values[SIMD_MAX_VALS]; 228 uint64_t b_values[SIMD_MAX_VALS]; 229 230 simdUnpack(a, a_values, fmt, sign); 231 simdUnpack(b, b_values, fmt, sign); 232 233 for (int i = 0; i < nvals; i++) { 234 if (saturate) 235 a_values[i] = dspSaturate(a_values[i] - b_values[i], fmt, sign, 236 &ouflag); 237 else 238 a_values[i] = checkOverflow(a_values[i] - b_values[i], fmt, sign, 239 &ouflag); 240 } 241 242 simdPack(a_values, &result, fmt); 243 244 if (ouflag) 245 writeDSPControl(dspctl, (ouflag << 4) << DSP_CTL_POS[DSP_OUFLAG], 246 1 << DSP_OUFLAG); 247 248 return result; 249} 250 251int32_t 252MipsISA::dspSubh(int32_t a, int32_t b, int32_t fmt, int32_t round, 253 int32_t sign) 254{ 255 int nvals = SIMD_NVALS[fmt]; 256 int32_t result; 257 uint64_t a_values[SIMD_MAX_VALS]; 258 uint64_t b_values[SIMD_MAX_VALS]; 259 260 simdUnpack(a, a_values, fmt, sign); 261 simdUnpack(b, b_values, fmt, sign); 262 263 for (int i = 0; i < nvals; i++) 264 { 265 if (round) 266 a_values[i] = addHalfLsb(a_values[i] - b_values[i], 1) >> 1; 267 else 268 a_values[i] = (a_values[i] - b_values[i]) >> 1; 269 } 270 271 simdPack(a_values, &result, fmt); 272 273 return result; 274} 275 276int32_t 277MipsISA::dspShll(int32_t a, uint32_t sa, int32_t fmt, int32_t saturate, 278 int32_t sign, uint32_t *dspctl) 279{ 280 int nvals = SIMD_NVALS[fmt]; 281 int32_t result; 282 uint32_t ouflag = 0; 283 uint64_t a_values[SIMD_MAX_VALS]; 284 285 sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0); 286 simdUnpack(a, a_values, fmt, sign); 287 288 for (int i = 0; i < nvals; i++) 289 { 290 if (saturate) 291 a_values[i] = dspSaturate(a_values[i] << sa, fmt, sign, &ouflag); 292 else 293 a_values[i] = checkOverflow(a_values[i] << sa, fmt, sign, &ouflag); 294 } 295 296 simdPack(a_values, &result, fmt); 297 298 if (ouflag) 299 writeDSPControl(dspctl, (ouflag << 6) << DSP_CTL_POS[DSP_OUFLAG], 300 1 << DSP_OUFLAG); 301 302 return result; 303} 304 305int32_t 306MipsISA::dspShrl(int32_t a, uint32_t sa, int32_t fmt, int32_t sign) 307{ 308 int nvals = SIMD_NVALS[fmt]; 309 int32_t result; 310 uint64_t a_values[SIMD_MAX_VALS]; 311 312 sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0); 313 314 simdUnpack(a, a_values, fmt, UNSIGNED); 315 316 for (int i = 0; i < nvals; i++) 317 a_values[i] = a_values[i] >> sa; 318 319 simdPack(a_values, &result, fmt); 320 321 return result; 322} 323 324int32_t 325MipsISA::dspShra(int32_t a, uint32_t sa, int32_t fmt, int32_t round, 326 int32_t sign, uint32_t *dspctl) 327{ 328 int nvals = SIMD_NVALS[fmt]; 329 int32_t result; 330 uint64_t a_values[SIMD_MAX_VALS]; 331 332 sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0); 333 334 simdUnpack(a, a_values, fmt, SIGNED); 335 336 for (int i = 0; i < nvals; i++) { 337 if (round) 338 a_values[i] = addHalfLsb(a_values[i], sa) >> sa; 339 else 340 a_values[i] = a_values[i] >> sa; 341 } 342 343 simdPack(a_values, &result, fmt); 344 345 return result; 346} 347 348int32_t 349MipsISA::dspMulq(int32_t a, int32_t b, int32_t fmt, int32_t saturate, 350 int32_t round, uint32_t *dspctl) 351{ 352 int nvals = SIMD_NVALS[fmt]; 353 int sa = SIMD_NBITS[fmt]; 354 int32_t result; 355 uint32_t ouflag = 0; 356 uint64_t a_values[SIMD_MAX_VALS]; 357 uint64_t b_values[SIMD_MAX_VALS]; 358 int64_t temp; 359 360 simdUnpack(a, a_values, fmt, SIGNED); 361 simdUnpack(b, b_values, fmt, SIGNED); 362 363 for (int i = 0; i < nvals; i++) { 364 if (round) 365 temp = 366 (int64_t)addHalfLsb(a_values[i] * b_values[i] << 1, sa) >> sa; 367 else 368 temp = (int64_t)(a_values[i] * b_values[i]) >> (sa - 1); 369 370 if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) { 371 ouflag = 1; 372 373 if (saturate) 374 temp = FIXED_SMAX[fmt]; 375 } 376 377 a_values[i] = temp; 378 } 379 380 simdPack(a_values, &result, fmt); 381 382 if (ouflag) 383 writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG], 384 1 << DSP_OUFLAG); 385 386 return result; 387} 388 389int32_t 390MipsISA::dspMul(int32_t a, int32_t b, int32_t fmt, int32_t saturate, 391 uint32_t *dspctl) 392{ 393 int nvals = SIMD_NVALS[fmt]; 394 int32_t result; 395 uint32_t ouflag = 0; 396 uint64_t a_values[SIMD_MAX_VALS]; 397 uint64_t b_values[SIMD_MAX_VALS]; 398 399 simdUnpack(a, a_values, fmt, SIGNED); 400 simdUnpack(b, b_values, fmt, SIGNED); 401 402 for (int i = 0; i < nvals; i++) 403 { 404 if (saturate) 405 a_values[i] = dspSaturate(a_values[i] * b_values[i], fmt, SIGNED, 406 &ouflag); 407 else 408 a_values[i] = checkOverflow(a_values[i] * b_values[i], fmt, SIGNED, 409 &ouflag); 410 } 411 412 simdPack(a_values, &result, fmt); 413 414 if (ouflag) 415 writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG], 416 1 << DSP_OUFLAG); 417 418 return result; 419} 420 421int32_t 422MipsISA::dspMuleu(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl) 423{ 424 int nvals = SIMD_NVALS[SIMD_FMT_PH]; 425 int32_t result; 426 uint32_t ouflag = 0; 427 uint64_t a_values[SIMD_MAX_VALS]; 428 uint64_t b_values[SIMD_MAX_VALS]; 429 430 simdUnpack(a, a_values, SIMD_FMT_QB, UNSIGNED); 431 simdUnpack(b, b_values, SIMD_FMT_PH, UNSIGNED); 432 433 switch (mode) { 434 case MODE_L: 435 for (int i = 0; i < nvals; i++) 436 b_values[i] = dspSaturate(a_values[i + 2] * b_values[i], 437 SIMD_FMT_PH, UNSIGNED, &ouflag); 438 break; 439 case MODE_R: 440 for (int i = 0; i < nvals; i++) 441 b_values[i] = dspSaturate(a_values[i] * b_values[i], SIMD_FMT_PH, 442 UNSIGNED, &ouflag); 443 break; 444 } 445 446 simdPack(b_values, &result, SIMD_FMT_PH); 447 448 if (ouflag) 449 writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG], 450 1 << DSP_OUFLAG); 451 452 return result; 453} 454 455int32_t 456MipsISA::dspMuleq(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl) 457{ 458 int nvals = SIMD_NVALS[SIMD_FMT_W]; 459 int32_t result; 460 uint32_t ouflag = 0; 461 uint64_t a_values[SIMD_MAX_VALS]; 462 uint64_t b_values[SIMD_MAX_VALS]; 463 uint64_t c_values[SIMD_MAX_VALS]; 464 465 memset(c_values, 0, sizeof(c_values)); 466 467 simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED); 468 simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED); 469 470 switch (mode) { 471 case MODE_L: 472 for (int i = 0; i < nvals; i++) 473 c_values[i] = dspSaturate(a_values[i + 1] * b_values[i + 1] << 1, 474 SIMD_FMT_W, SIGNED, &ouflag); 475 break; 476 case MODE_R: 477 for (int i = 0; i < nvals; i++) 478 c_values[i] = dspSaturate(a_values[i] * b_values[i] << 1, 479 SIMD_FMT_W, SIGNED, &ouflag); 480 break; 481 } 482 483 simdPack(c_values, &result, SIMD_FMT_W); 484 485 if (ouflag) 486 writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG], 487 1 << DSP_OUFLAG); 488 489 return result; 490} 491 492int64_t 493MipsISA::dspDpaq(int64_t dspac, int32_t a, int32_t b, int32_t ac, 494 int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode, 495 uint32_t *dspctl) 496{ 497 int nvals = SIMD_NVALS[infmt]; 498 int64_t result = 0; 499 int64_t temp = 0; 500 uint32_t ouflag = 0; 501 uint64_t a_values[SIMD_MAX_VALS]; 502 uint64_t b_values[SIMD_MAX_VALS]; 503 504 simdUnpack(a, a_values, infmt, SIGNED); 505 simdUnpack(b, b_values, infmt, SIGNED); 506 507 for (int i = 0; i < nvals; i++) { 508 switch (mode) { 509 case MODE_X: 510 if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] && 511 b_values[i] == FIXED_SMIN[infmt]) { 512 result += FIXED_SMAX[outfmt]; 513 ouflag = 1; 514 } 515 else 516 result += a_values[nvals - 1 - i] * b_values[i] << 1; 517 break; 518 default: 519 if (a_values[i] == FIXED_SMIN[infmt] && 520 b_values[i] == FIXED_SMIN[infmt]) { 521 result += FIXED_SMAX[outfmt]; 522 ouflag = 1; 523 } else { 524 result += a_values[i] * b_values[i] << 1; 525 } 526 break; 527 } 528 } 529 530 if (postsat) { 531 if (outfmt == SIMD_FMT_L) { 532 int signa = bits(dspac, 63, 63); 533 int signb = bits(result, 63, 63); 534 535 temp = dspac + result; 536 537 if (signa == signb && bits(temp, 63, 63) != signa) { 538 ouflag = 1; 539 if (signa) 540 dspac = FIXED_SMIN[outfmt]; 541 else 542 dspac = FIXED_SMAX[outfmt]; 543 } else { 544 dspac = temp; 545 } 546 } else { 547 dspac = dspSaturate(dspac + result, outfmt, SIGNED, &ouflag); 548 } 549 } else { 550 dspac += result; 551 } 552 553 if (ouflag) 554 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1); 555 556 return dspac; 557} 558 559int64_t 560MipsISA::dspDpsq(int64_t dspac, int32_t a, int32_t b, int32_t ac, 561 int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode, 562 uint32_t *dspctl) 563{ 564 int nvals = SIMD_NVALS[infmt]; 565 int64_t result = 0; 566 int64_t temp = 0; 567 uint32_t ouflag = 0; 568 uint64_t a_values[SIMD_MAX_VALS]; 569 uint64_t b_values[SIMD_MAX_VALS]; 570 571 simdUnpack(a, a_values, infmt, SIGNED); 572 simdUnpack(b, b_values, infmt, SIGNED); 573 574 for (int i = 0; i < nvals; i++) { 575 switch (mode) { 576 case MODE_X: 577 if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] && 578 b_values[i] == FIXED_SMIN[infmt]) { 579 result += FIXED_SMAX[outfmt]; 580 ouflag = 1; 581 } else { 582 result += a_values[nvals - 1 - i] * b_values[i] << 1; 583 } 584 break; 585 default: 586 if (a_values[i] == FIXED_SMIN[infmt] && 587 b_values[i] == FIXED_SMIN[infmt]) { 588 result += FIXED_SMAX[outfmt]; 589 ouflag = 1; 590 } else { 591 result += a_values[i] * b_values[i] << 1; 592 } 593 break; 594 } 595 } 596 597 if (postsat) { 598 if (outfmt == SIMD_FMT_L) { 599 int signa = bits(dspac, 63, 63); 600 int signb = bits(-result, 63, 63); 601 602 temp = dspac - result; 603 604 if (signa == signb && bits(temp, 63, 63) != signa) { 605 ouflag = 1; 606 if (signa) 607 dspac = FIXED_SMIN[outfmt]; 608 else 609 dspac = FIXED_SMAX[outfmt]; 610 } else { 611 dspac = temp; 612 } 613 } else { 614 dspac = dspSaturate(dspac - result, outfmt, SIGNED, &ouflag); 615 } 616 } else { 617 dspac -= result; 618 } 619 620 if (ouflag) 621 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1); 622 623 return dspac; 624} 625 626int64_t 627MipsISA::dspDpa(int64_t dspac, int32_t a, int32_t b, int32_t ac, 628 int32_t fmt, int32_t sign, int32_t mode) 629{ 630 int nvals = SIMD_NVALS[fmt]; 631 uint64_t a_values[SIMD_MAX_VALS]; 632 uint64_t b_values[SIMD_MAX_VALS]; 633 634 simdUnpack(a, a_values, fmt, sign); 635 simdUnpack(b, b_values, fmt, sign); 636 637 for (int i = 0; i < 2; i++) { 638 switch (mode) { 639 case MODE_L: 640 dspac += a_values[nvals - 1 - i] * b_values[nvals - 1 - i]; 641 break; 642 case MODE_R: 643 dspac += a_values[nvals - 3 - i] * b_values[nvals - 3 - i]; 644 break; 645 case MODE_X: 646 dspac += a_values[nvals - 1 - i] * b_values[i]; 647 break; 648 } 649 } 650 651 return dspac; 652} 653 654int64_t 655MipsISA::dspDps(int64_t dspac, int32_t a, int32_t b, int32_t ac, 656 int32_t fmt, int32_t sign, int32_t mode) 657{ 658 int nvals = SIMD_NVALS[fmt]; 659 uint64_t a_values[SIMD_MAX_VALS]; 660 uint64_t b_values[SIMD_MAX_VALS]; 661 662 simdUnpack(a, a_values, fmt, sign); 663 simdUnpack(b, b_values, fmt, sign); 664 665 for (int i = 0; i < 2; i++) { 666 switch (mode) { 667 case MODE_L: 668 dspac -= a_values[nvals - 1 - i] * b_values[nvals - 1 - i]; 669 break; 670 case MODE_R: 671 dspac -= a_values[nvals - 3 - i] * b_values[nvals - 3 - i]; 672 break; 673 case MODE_X: 674 dspac -= a_values[nvals - 1 - i] * b_values[i]; 675 break; 676 } 677 } 678 679 return dspac; 680} 681 682int64_t 683MipsISA::dspMaq(int64_t dspac, int32_t a, int32_t b, int32_t ac, 684 int32_t fmt, int32_t mode, int32_t saturate, uint32_t *dspctl) 685{ 686 int nvals = SIMD_NVALS[fmt - 1]; 687 uint64_t a_values[SIMD_MAX_VALS]; 688 uint64_t b_values[SIMD_MAX_VALS]; 689 int64_t temp = 0; 690 uint32_t ouflag = 0; 691 692 simdUnpack(a, a_values, fmt, SIGNED); 693 simdUnpack(b, b_values, fmt, SIGNED); 694 695 for (int i = 0; i < nvals; i++) { 696 switch (mode) { 697 case MODE_L: 698 temp = a_values[i + 1] * b_values[i + 1] << 1; 699 if (a_values[i + 1] == FIXED_SMIN[fmt] && 700 b_values[i + 1] == FIXED_SMIN[fmt]) { 701 temp = (int64_t)FIXED_SMAX[fmt - 1]; 702 ouflag = 1; 703 } 704 break; 705 case MODE_R: 706 temp = a_values[i] * b_values[i] << 1; 707 if (a_values[i] == FIXED_SMIN[fmt] && 708 b_values[i] == FIXED_SMIN[fmt]) { 709 temp = (int64_t)FIXED_SMAX[fmt - 1]; 710 ouflag = 1; 711 } 712 break; 713 } 714 715 temp += dspac; 716 717 if (saturate) 718 temp = dspSaturate(temp, fmt - 1, SIGNED, &ouflag); 719 if (ouflag) 720 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1); 721 } 722 723 return temp; 724} 725 726int64_t 727MipsISA::dspMulsa(int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt) 728{ 729 uint64_t a_values[SIMD_MAX_VALS]; 730 uint64_t b_values[SIMD_MAX_VALS]; 731 732 simdUnpack(a, a_values, fmt, SIGNED); 733 simdUnpack(b, b_values, fmt, SIGNED); 734 735 dspac += a_values[1] * b_values[1] - a_values[0] * b_values[0]; 736 737 return dspac; 738} 739 740int64_t 741MipsISA::dspMulsaq(int64_t dspac, int32_t a, int32_t b, int32_t ac, 742 int32_t fmt, uint32_t *dspctl) 743{ 744 int nvals = SIMD_NVALS[fmt]; 745 uint64_t a_values[SIMD_MAX_VALS]; 746 uint64_t b_values[SIMD_MAX_VALS]; 747 int64_t temp[2] = {0, 0}; 748 uint32_t ouflag = 0; 749 750 simdUnpack(a, a_values, fmt, SIGNED); 751 simdUnpack(b, b_values, fmt, SIGNED); 752 753 for (int i = nvals - 1; i > -1; i--) { 754 temp[i] = a_values[i] * b_values[i] << 1; 755 if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) { 756 temp[i] = FIXED_SMAX[fmt - 1]; 757 ouflag = 1; 758 } 759 } 760 761 dspac += temp[1] - temp[0]; 762 763 if (ouflag) 764 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1); 765 766 return dspac; 767} 768 769void 770MipsISA::dspCmp(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, 771 uint32_t *dspctl) 772{ 773 int nvals = SIMD_NVALS[fmt]; 774 int ccond = 0; 775 uint64_t a_values[SIMD_MAX_VALS]; 776 uint64_t b_values[SIMD_MAX_VALS]; 777 778 simdUnpack(a, a_values, fmt, sign); 779 simdUnpack(b, b_values, fmt, sign); 780 781 for (int i = 0; i < nvals; i++) { 782 int cc = 0; 783 784 switch (op) { 785 case CMP_EQ: 786 cc = (a_values[i] == b_values[i]); 787 break; 788 case CMP_LT: 789 cc = (a_values[i] < b_values[i]); 790 break; 791 case CMP_LE: 792 cc = (a_values[i] <= b_values[i]); 793 break; 794 } 795 796 ccond |= cc << (DSP_CTL_POS[DSP_CCOND] + i); 797 } 798 799 writeDSPControl(dspctl, ccond, 1 << DSP_CCOND); 800} 801 802int32_t 803MipsISA::dspCmpg(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op) 804{ 805 int nvals = SIMD_NVALS[fmt]; 806 int32_t result = 0; 807 uint64_t a_values[SIMD_MAX_VALS]; 808 uint64_t b_values[SIMD_MAX_VALS]; 809 810 simdUnpack(a, a_values, fmt, sign); 811 simdUnpack(b, b_values, fmt, sign); 812 813 for (int i = 0; i < nvals; i++) { 814 int cc = 0; 815 816 switch (op) { 817 case CMP_EQ: 818 cc = (a_values[i] == b_values[i]); 819 break; 820 case CMP_LT: 821 cc = (a_values[i] < b_values[i]); 822 break; 823 case CMP_LE: 824 cc = (a_values[i] <= b_values[i]); 825 break; 826 } 827 828 result |= cc << i; 829 } 830 831 return result; 832} 833 834int32_t 835MipsISA::dspCmpgd(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, 836 uint32_t *dspctl) 837{ 838 int nvals = SIMD_NVALS[fmt]; 839 int32_t result = 0; 840 int ccond = 0; 841 uint64_t a_values[SIMD_MAX_VALS]; 842 uint64_t b_values[SIMD_MAX_VALS]; 843 844 simdUnpack(a, a_values, fmt, sign); 845 simdUnpack(b, b_values, fmt, sign); 846 847 for (int i = 0; i < nvals; i++) { 848 int cc = 0; 849 850 switch (op) { 851 case CMP_EQ: 852 cc = (a_values[i] == b_values[i]); 853 break; 854 case CMP_LT: 855 cc = (a_values[i] < b_values[i]); 856 break; 857 case CMP_LE: 858 cc = (a_values[i] <= b_values[i]); 859 break; 860 } 861 862 result |= cc << i; 863 ccond |= cc << (DSP_CTL_POS[DSP_CCOND] + i); 864 } 865 866 writeDSPControl(dspctl, ccond, 1 << DSP_CCOND); 867 868 return result; 869} 870 871int32_t 872MipsISA::dspPrece(int32_t a, int32_t infmt, int32_t insign, int32_t outfmt, 873 int32_t outsign, int32_t mode) 874{ 875 int sa = 0; 876 int ninvals = SIMD_NVALS[infmt]; 877 int noutvals = SIMD_NVALS[outfmt]; 878 int32_t result; 879 uint64_t in_values[SIMD_MAX_VALS]; 880 uint64_t out_values[SIMD_MAX_VALS]; 881 882 if (insign == SIGNED && outsign == SIGNED) 883 sa = SIMD_NBITS[infmt]; 884 else if (insign == UNSIGNED && outsign == SIGNED) 885 sa = SIMD_NBITS[infmt] - 1; 886 else if (insign == UNSIGNED && outsign == UNSIGNED) 887 sa = 0; 888 889 simdUnpack(a, in_values, infmt, insign); 890 891 for (int i = 0; i<noutvals; i++) { 892 switch (mode) { 893 case MODE_L: 894 out_values[i] = in_values[i + (ninvals >> 1)] << sa; 895 break; 896 case MODE_R: 897 out_values[i] = in_values[i] << sa; 898 break; 899 case MODE_LA: 900 out_values[i] = in_values[(i << 1) + 1] << sa; 901 break; 902 case MODE_RA: 903 out_values[i] = in_values[i << 1] << sa; 904 break; 905 } 906 } 907 908 simdPack(out_values, &result, outfmt); 909 910 return result; 911} 912 913int32_t 914MipsISA::dspPrecrqu(int32_t a, int32_t b, uint32_t *dspctl) 915{ 916 uint64_t a_values[SIMD_MAX_VALS]; 917 uint64_t b_values[SIMD_MAX_VALS]; 918 uint64_t r_values[SIMD_MAX_VALS]; 919 uint32_t ouflag = 0; 920 int32_t result = 0; 921 922 simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED); 923 simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED); 924 925 for (int i = 0; i<2; i++) { 926 r_values[i] = 927 dspSaturate((int64_t)b_values[i] >> (SIMD_NBITS[SIMD_FMT_QB] - 1), 928 SIMD_FMT_QB, UNSIGNED, &ouflag); 929 r_values[i + 2] = 930 dspSaturate((int64_t)a_values[i] >> (SIMD_NBITS[SIMD_FMT_QB] - 1), 931 SIMD_FMT_QB, UNSIGNED, &ouflag); 932 } 933 934 simdPack(r_values, &result, SIMD_FMT_QB); 935 936 if (ouflag) 937 *dspctl = insertBits(*dspctl, 22, 22, 1); 938 939 return result; 940} 941 942int32_t 943MipsISA::dspPrecrq(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl) 944{ 945 uint64_t a_values[SIMD_MAX_VALS]; 946 uint64_t b_values[SIMD_MAX_VALS]; 947 uint64_t r_values[SIMD_MAX_VALS]; 948 uint32_t ouflag = 0; 949 int32_t result; 950 951 simdUnpack(a, a_values, fmt, SIGNED); 952 simdUnpack(b, b_values, fmt, SIGNED); 953 954 r_values[1] = dspSaturate((int64_t)addHalfLsb(a_values[0], 16) >> 16, 955 fmt + 1, SIGNED, &ouflag); 956 r_values[0] = dspSaturate((int64_t)addHalfLsb(b_values[0], 16) >> 16, 957 fmt + 1, SIGNED, &ouflag); 958 959 simdPack(r_values, &result, fmt + 1); 960 961 if (ouflag) 962 *dspctl = insertBits(*dspctl, 22, 22, 1); 963 964 return result; 965} 966 967int32_t 968MipsISA::dspPrecrSra(int32_t a, int32_t b, int32_t sa, int32_t fmt, 969 int32_t round) 970{ 971 int nvals = SIMD_NVALS[fmt]; 972 uint64_t a_values[SIMD_MAX_VALS]; 973 uint64_t b_values[SIMD_MAX_VALS]; 974 uint64_t c_values[SIMD_MAX_VALS]; 975 int32_t result = 0; 976 977 simdUnpack(a, a_values, fmt, SIGNED); 978 simdUnpack(b, b_values, fmt, SIGNED); 979 980 for (int i = 0; i < nvals; i++) { 981 if (round) { 982 c_values[i] = addHalfLsb(b_values[i], sa) >> sa; 983 c_values[i + 1] = addHalfLsb(a_values[i], sa) >> sa; 984 } else { 985 c_values[i] = b_values[i] >> sa; 986 c_values[i + 1] = a_values[i] >> sa; 987 } 988 } 989 990 simdPack(c_values, &result, fmt + 1); 991 992 return result; 993} 994 995int32_t 996MipsISA::dspPick(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl) 997{ 998 int nvals = SIMD_NVALS[fmt]; 999 int32_t result; 1000 uint64_t a_values[SIMD_MAX_VALS]; 1001 uint64_t b_values[SIMD_MAX_VALS]; 1002 uint64_t c_values[SIMD_MAX_VALS]; 1003 1004 simdUnpack(a, a_values, fmt, UNSIGNED); 1005 simdUnpack(b, b_values, fmt, UNSIGNED); 1006 1007 for (int i = 0; i < nvals; i++) { 1008 int condbit = DSP_CTL_POS[DSP_CCOND] + i; 1009 if (bits(*dspctl, condbit, condbit) == 1) 1010 c_values[i] = a_values[i]; 1011 else 1012 c_values[i] = b_values[i]; 1013 } 1014 1015 simdPack(c_values, &result, fmt); 1016 1017 return result; 1018} 1019 1020int32_t 1021MipsISA::dspPack(int32_t a, int32_t b, int32_t fmt) 1022{ 1023 int32_t result; 1024 uint64_t a_values[SIMD_MAX_VALS]; 1025 uint64_t b_values[SIMD_MAX_VALS]; 1026 uint64_t c_values[SIMD_MAX_VALS]; 1027 1028 simdUnpack(a, a_values, fmt, UNSIGNED); 1029 simdUnpack(b, b_values, fmt, UNSIGNED); 1030 1031 c_values[0] = b_values[1]; 1032 c_values[1] = a_values[0]; 1033 1034 simdPack(c_values, &result, fmt); 1035 1036 return result; 1037} 1038 1039int32_t 1040MipsISA::dspExtr(int64_t dspac, int32_t fmt, int32_t sa, int32_t round, 1041 int32_t saturate, uint32_t *dspctl) 1042{ 1043 int32_t result = 0; 1044 uint32_t ouflag = 0; 1045 int64_t temp = 0; 1046 1047 sa = bits(sa, 4, 0); 1048 1049 if (sa > 0) { 1050 if (round) { 1051 temp = (int64_t)addHalfLsb(dspac, sa); 1052 1053 if (dspac > 0 && temp < 0) { 1054 ouflag = 1; 1055 if (saturate) 1056 temp = FIXED_SMAX[SIMD_FMT_L]; 1057 } 1058 temp = temp >> sa; 1059 } else { 1060 temp = dspac >> sa; 1061 } 1062 } else { 1063 temp = dspac; 1064 } 1065 1066 dspac = checkOverflow(dspac, fmt, SIGNED, &ouflag); 1067 1068 if (ouflag) { 1069 *dspctl = insertBits(*dspctl, 23, 23, ouflag); 1070 1071 if (saturate) 1072 result = (int32_t)dspSaturate(temp, fmt, SIGNED, &ouflag); 1073 else 1074 result = (int32_t)temp; 1075 } else { 1076 result = (int32_t)temp; 1077 } 1078 1079 return result; 1080} 1081 1082int32_t 1083MipsISA::dspExtp(int64_t dspac, int32_t size, uint32_t *dspctl) 1084{ 1085 int32_t pos = 0; 1086 int32_t result = 0; 1087 1088 pos = bits(*dspctl, 5, 0); 1089 size = bits(size, 4, 0); 1090 1091 if (pos - (size + 1) >= -1) { 1092 result = bits(dspac, pos, pos - size); 1093 *dspctl = insertBits(*dspctl, 14, 14, 0); 1094 } else { 1095 result = 0; 1096 *dspctl = insertBits(*dspctl, 14, 14, 1); 1097 } 1098 1099 return result; 1100} 1101 1102int32_t 1103MipsISA::dspExtpd(int64_t dspac, int32_t size, uint32_t *dspctl) 1104{ 1105 int32_t pos = 0; 1106 int32_t result = 0; 1107 1108 pos = bits(*dspctl, 5, 0); 1109 size = bits(size, 4, 0); 1110 1111 if (pos - (size + 1) >= -1) { 1112 result = bits(dspac, pos, pos - size); 1113 *dspctl = insertBits(*dspctl, 14, 14, 0); 1114 if (pos - (size + 1) >= 0) 1115 *dspctl = insertBits(*dspctl, 5, 0, pos - (size + 1)); 1116 else if ((pos - (size + 1)) == -1) 1117 *dspctl = insertBits(*dspctl, 5, 0, 63); 1118 } else { 1119 result = 0; 1120 *dspctl = insertBits(*dspctl, 14, 14, 1); 1121 } 1122 1123 return result; 1124} 1125 1126void 1127MipsISA::simdPack(uint64_t *values_ptr, int32_t *reg, int32_t fmt) 1128{ 1129 int nvals = SIMD_NVALS[fmt]; 1130 int nbits = SIMD_NBITS[fmt]; 1131 1132 *reg = 0; 1133 1134 for (int i = 0; i < nvals; i++) 1135 *reg |= (int32_t)bits(values_ptr[i], nbits - 1, 0) << nbits * i; 1136} 1137 1138void 1139MipsISA::simdUnpack(int32_t reg, uint64_t *values_ptr, int32_t fmt, int32_t sign) 1140{ 1141 int nvals = SIMD_NVALS[fmt]; 1142 int nbits = SIMD_NBITS[fmt]; 1143 1144 switch (sign) { 1145 case SIGNED: 1146 for (int i = 0; i < nvals; i++) { 1147 uint64_t tmp = (uint64_t)bits(reg, nbits * (i + 1) - 1, nbits * i); 1148 values_ptr[i] = signExtend(tmp, fmt); 1149 } 1150 break; 1151 case UNSIGNED: 1152 for (int i = 0; i < nvals; i++) { 1153 values_ptr[i] = 1154 (uint64_t)bits(reg, nbits * (i + 1) - 1, nbits * i); 1155 } 1156 break; 1157 } 1158} 1159 1160void 1161MipsISA::writeDSPControl(uint32_t *dspctl, uint32_t value, uint32_t mask) 1162{ 1163 uint32_t fmask = 0; 1164 1165 if (mask & 0x01) fmask |= DSP_CTL_MASK[DSP_POS]; 1166 if (mask & 0x02) fmask |= DSP_CTL_MASK[DSP_SCOUNT]; 1167 if (mask & 0x04) fmask |= DSP_CTL_MASK[DSP_C]; 1168 if (mask & 0x08) fmask |= DSP_CTL_MASK[DSP_OUFLAG]; 1169 if (mask & 0x10) fmask |= DSP_CTL_MASK[DSP_CCOND]; 1170 if (mask & 0x20) fmask |= DSP_CTL_MASK[DSP_EFI]; 1171 1172 *dspctl &= ~fmask; 1173 value &= fmask; 1174 *dspctl |= value; 1175} 1176 1177uint32_t 1178MipsISA::readDSPControl(uint32_t *dspctl, uint32_t mask) 1179{ 1180 uint32_t fmask = 0; 1181 1182 if (mask & 0x01) fmask |= DSP_CTL_MASK[DSP_POS]; 1183 if (mask & 0x02) fmask |= DSP_CTL_MASK[DSP_SCOUNT]; 1184 if (mask & 0x04) fmask |= DSP_CTL_MASK[DSP_C]; 1185 if (mask & 0x08) fmask |= DSP_CTL_MASK[DSP_OUFLAG]; 1186 if (mask & 0x10) fmask |= DSP_CTL_MASK[DSP_CCOND]; 1187 if (mask & 0x20) fmask |= DSP_CTL_MASK[DSP_EFI]; 1188 1189 return *dspctl & fmask; 1190} 1191