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