dsp.cc revision 5563
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/isa_traits.hh" 32#include "arch/mips/dsp.hh" 33#include "config/full_system.hh" 34#include "cpu/static_inst.hh" 35#include "sim/serialize.hh" 36#include "base/bitfield.hh" 37#include "base/misc.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 simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED); 467 simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED); 468 469 switch (mode) { 470 case MODE_L: 471 for (int i = 0; i < nvals; i++) 472 c_values[i] = dspSaturate(a_values[i + 1] * b_values[i + 1] << 1, 473 SIMD_FMT_W, SIGNED, &ouflag); 474 break; 475 case MODE_R: 476 for (int i = 0; i < nvals; i++) 477 c_values[i] = dspSaturate(a_values[i] * b_values[i] << 1, 478 SIMD_FMT_W, SIGNED, &ouflag); 479 break; 480 } 481 482 simdPack(c_values, &result, SIMD_FMT_W); 483 484 if (ouflag) 485 writeDSPControl(dspctl, (ouflag << 5) << DSP_CTL_POS[DSP_OUFLAG], 486 1 << DSP_OUFLAG); 487 488 return result; 489} 490 491int64_t 492MipsISA::dspDpaq(int64_t dspac, int32_t a, int32_t b, int32_t ac, 493 int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode, 494 uint32_t *dspctl) 495{ 496 int nvals = SIMD_NVALS[infmt]; 497 int64_t result = 0; 498 int64_t temp = 0; 499 uint32_t ouflag = 0; 500 uint64_t a_values[SIMD_MAX_VALS]; 501 uint64_t b_values[SIMD_MAX_VALS]; 502 503 simdUnpack(a, a_values, infmt, SIGNED); 504 simdUnpack(b, b_values, infmt, SIGNED); 505 506 for (int i = 0; i < nvals; i++) { 507 switch (mode) { 508 case MODE_X: 509 if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] && 510 b_values[i] == FIXED_SMIN[infmt]) { 511 result += FIXED_SMAX[outfmt]; 512 ouflag = 1; 513 } 514 else 515 result += a_values[nvals - 1 - i] * b_values[i] << 1; 516 break; 517 default: 518 if (a_values[i] == FIXED_SMIN[infmt] && 519 b_values[i] == FIXED_SMIN[infmt]) { 520 result += FIXED_SMAX[outfmt]; 521 ouflag = 1; 522 } else { 523 result += a_values[i] * b_values[i] << 1; 524 } 525 break; 526 } 527 } 528 529 if (postsat) { 530 if (outfmt == SIMD_FMT_L) { 531 int signa = bits(dspac, 63, 63); 532 int signb = bits(result, 63, 63); 533 534 temp = dspac + result; 535 536 if (signa == signb && bits(temp, 63, 63) != signa) { 537 ouflag = 1; 538 if (signa) 539 dspac = FIXED_SMIN[outfmt]; 540 else 541 dspac = FIXED_SMAX[outfmt]; 542 } else { 543 dspac = temp; 544 } 545 } else { 546 dspac = dspSaturate(dspac + result, outfmt, SIGNED, &ouflag); 547 } 548 } else { 549 dspac += result; 550 } 551 552 if (ouflag) 553 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1); 554 555 return dspac; 556} 557 558int64_t 559MipsISA::dspDpsq(int64_t dspac, int32_t a, int32_t b, int32_t ac, 560 int32_t infmt, int32_t outfmt, int32_t postsat, int32_t mode, 561 uint32_t *dspctl) 562{ 563 int nvals = SIMD_NVALS[infmt]; 564 int64_t result = 0; 565 int64_t temp = 0; 566 uint32_t ouflag = 0; 567 uint64_t a_values[SIMD_MAX_VALS]; 568 uint64_t b_values[SIMD_MAX_VALS]; 569 570 simdUnpack(a, a_values, infmt, SIGNED); 571 simdUnpack(b, b_values, infmt, SIGNED); 572 573 for (int i = 0; i < nvals; i++) { 574 switch (mode) { 575 case MODE_X: 576 if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] && 577 b_values[i] == FIXED_SMIN[infmt]) { 578 result += FIXED_SMAX[outfmt]; 579 ouflag = 1; 580 } else { 581 result += a_values[nvals - 1 - i] * b_values[i] << 1; 582 } 583 break; 584 default: 585 if (a_values[i] == FIXED_SMIN[infmt] && 586 b_values[i] == FIXED_SMIN[infmt]) { 587 result += FIXED_SMAX[outfmt]; 588 ouflag = 1; 589 } else { 590 result += a_values[i] * b_values[i] << 1; 591 } 592 break; 593 } 594 } 595 596 if (postsat) { 597 if (outfmt == SIMD_FMT_L) { 598 int signa = bits(dspac, 63, 63); 599 int signb = bits(-result, 63, 63); 600 601 temp = dspac - result; 602 603 if (signa == signb && bits(temp, 63, 63) != signa) { 604 ouflag = 1; 605 if (signa) 606 dspac = FIXED_SMIN[outfmt]; 607 else 608 dspac = FIXED_SMAX[outfmt]; 609 } else { 610 dspac = temp; 611 } 612 } else { 613 dspac = dspSaturate(dspac - result, outfmt, SIGNED, &ouflag); 614 } 615 } else { 616 dspac -= result; 617 } 618 619 if (ouflag) 620 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1); 621 622 return dspac; 623} 624 625int64_t 626MipsISA::dspDpa(int64_t dspac, int32_t a, int32_t b, int32_t ac, 627 int32_t fmt, int32_t sign, int32_t mode) 628{ 629 int nvals = SIMD_NVALS[fmt]; 630 uint64_t a_values[SIMD_MAX_VALS]; 631 uint64_t b_values[SIMD_MAX_VALS]; 632 633 simdUnpack(a, a_values, fmt, sign); 634 simdUnpack(b, b_values, fmt, sign); 635 636 for (int i = 0; i < 2; i++) { 637 switch (mode) { 638 case MODE_L: 639 dspac += a_values[nvals - 1 - i] * b_values[nvals - 1 - i]; 640 break; 641 case MODE_R: 642 dspac += a_values[nvals - 3 - i] * b_values[nvals - 3 - i]; 643 break; 644 case MODE_X: 645 dspac += a_values[nvals - 1 - i] * b_values[i]; 646 break; 647 } 648 } 649 650 return dspac; 651} 652 653int64_t 654MipsISA::dspDps(int64_t dspac, int32_t a, int32_t b, int32_t ac, 655 int32_t fmt, int32_t sign, int32_t mode) 656{ 657 int nvals = SIMD_NVALS[fmt]; 658 uint64_t a_values[SIMD_MAX_VALS]; 659 uint64_t b_values[SIMD_MAX_VALS]; 660 661 simdUnpack(a, a_values, fmt, sign); 662 simdUnpack(b, b_values, fmt, sign); 663 664 for (int i = 0; i < 2; i++) { 665 switch (mode) { 666 case MODE_L: 667 dspac -= a_values[nvals - 1 - i] * b_values[nvals - 1 - i]; 668 break; 669 case MODE_R: 670 dspac -= a_values[nvals - 3 - i] * b_values[nvals - 3 - i]; 671 break; 672 case MODE_X: 673 dspac -= a_values[nvals - 1 - i] * b_values[i]; 674 break; 675 } 676 } 677 678 return dspac; 679} 680 681int64_t 682MipsISA::dspMaq(int64_t dspac, int32_t a, int32_t b, int32_t ac, 683 int32_t fmt, int32_t mode, int32_t saturate, uint32_t *dspctl) 684{ 685 int nvals = SIMD_NVALS[fmt - 1]; 686 uint64_t a_values[SIMD_MAX_VALS]; 687 uint64_t b_values[SIMD_MAX_VALS]; 688 int64_t temp = 0; 689 uint32_t ouflag = 0; 690 691 simdUnpack(a, a_values, fmt, SIGNED); 692 simdUnpack(b, b_values, fmt, SIGNED); 693 694 for (int i = 0; i < nvals; i++) { 695 switch (mode) { 696 case MODE_L: 697 temp = a_values[i + 1] * b_values[i + 1] << 1; 698 if (a_values[i + 1] == FIXED_SMIN[fmt] && 699 b_values[i + 1] == FIXED_SMIN[fmt]) { 700 temp = (int64_t)FIXED_SMAX[fmt - 1]; 701 ouflag = 1; 702 } 703 break; 704 case MODE_R: 705 temp = a_values[i] * b_values[i] << 1; 706 if (a_values[i] == FIXED_SMIN[fmt] && 707 b_values[i] == FIXED_SMIN[fmt]) { 708 temp = (int64_t)FIXED_SMAX[fmt - 1]; 709 ouflag = 1; 710 } 711 break; 712 } 713 714 temp += dspac; 715 716 if (saturate) 717 temp = dspSaturate(temp, fmt - 1, SIGNED, &ouflag); 718 if (ouflag) 719 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1); 720 } 721 722 return temp; 723} 724 725int64_t 726MipsISA::dspMulsa(int64_t dspac, int32_t a, int32_t b, int32_t ac, int32_t fmt) 727{ 728 uint64_t a_values[SIMD_MAX_VALS]; 729 uint64_t b_values[SIMD_MAX_VALS]; 730 731 simdUnpack(a, a_values, fmt, SIGNED); 732 simdUnpack(b, b_values, fmt, SIGNED); 733 734 dspac += a_values[1] * b_values[1] - a_values[0] * b_values[0]; 735 736 return dspac; 737} 738 739int64_t 740MipsISA::dspMulsaq(int64_t dspac, int32_t a, int32_t b, int32_t ac, 741 int32_t fmt, uint32_t *dspctl) 742{ 743 int nvals = SIMD_NVALS[fmt]; 744 uint64_t a_values[SIMD_MAX_VALS]; 745 uint64_t b_values[SIMD_MAX_VALS]; 746 int64_t temp[2]; 747 uint32_t ouflag = 0; 748 749 simdUnpack(a, a_values, fmt, SIGNED); 750 simdUnpack(b, b_values, fmt, SIGNED); 751 752 for (int i = nvals - 1; i > -1; i--) { 753 temp[i] = a_values[i] * b_values[i] << 1; 754 if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) { 755 temp[i] = FIXED_SMAX[fmt - 1]; 756 ouflag = 1; 757 } 758 } 759 760 dspac += temp[1] - temp[0]; 761 762 if (ouflag) 763 *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1); 764 765 return dspac; 766} 767 768void 769MipsISA::dspCmp(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, 770 uint32_t *dspctl) 771{ 772 int nvals = SIMD_NVALS[fmt]; 773 int ccond = 0; 774 uint64_t a_values[SIMD_MAX_VALS]; 775 uint64_t b_values[SIMD_MAX_VALS]; 776 777 simdUnpack(a, a_values, fmt, sign); 778 simdUnpack(b, b_values, fmt, sign); 779 780 for (int i = 0; i < nvals; i++) { 781 int cc = 0; 782 783 switch (op) { 784 case CMP_EQ: 785 cc = (a_values[i] == b_values[i]); 786 break; 787 case CMP_LT: 788 cc = (a_values[i] < b_values[i]); 789 break; 790 case CMP_LE: 791 cc = (a_values[i] <= b_values[i]); 792 break; 793 } 794 795 ccond |= cc << (DSP_CTL_POS[DSP_CCOND] + i); 796 } 797 798 writeDSPControl(dspctl, ccond, 1 << DSP_CCOND); 799} 800 801int32_t 802MipsISA::dspCmpg(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op) 803{ 804 int nvals = SIMD_NVALS[fmt]; 805 int32_t result = 0; 806 uint64_t a_values[SIMD_MAX_VALS]; 807 uint64_t b_values[SIMD_MAX_VALS]; 808 809 simdUnpack(a, a_values, fmt, sign); 810 simdUnpack(b, b_values, fmt, sign); 811 812 for (int i = 0; i < nvals; i++) { 813 int cc = 0; 814 815 switch (op) { 816 case CMP_EQ: 817 cc = (a_values[i] == b_values[i]); 818 break; 819 case CMP_LT: 820 cc = (a_values[i] < b_values[i]); 821 break; 822 case CMP_LE: 823 cc = (a_values[i] <= b_values[i]); 824 break; 825 } 826 827 result |= cc << i; 828 } 829 830 return result; 831} 832 833int32_t 834MipsISA::dspCmpgd(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, 835 uint32_t *dspctl) 836{ 837 int nvals = SIMD_NVALS[fmt]; 838 int32_t result = 0; 839 int ccond = 0; 840 uint64_t a_values[SIMD_MAX_VALS]; 841 uint64_t b_values[SIMD_MAX_VALS]; 842 843 simdUnpack(a, a_values, fmt, sign); 844 simdUnpack(b, b_values, fmt, sign); 845 846 for (int i = 0; i < nvals; i++) { 847 int cc = 0; 848 849 switch (op) { 850 case CMP_EQ: 851 cc = (a_values[i] == b_values[i]); 852 break; 853 case CMP_LT: 854 cc = (a_values[i] < b_values[i]); 855 break; 856 case CMP_LE: 857 cc = (a_values[i] <= b_values[i]); 858 break; 859 } 860 861 result |= cc << i; 862 ccond |= cc << (DSP_CTL_POS[DSP_CCOND] + i); 863 } 864 865 writeDSPControl(dspctl, ccond, 1 << DSP_CCOND); 866 867 return result; 868} 869 870int32_t 871MipsISA::dspPrece(int32_t a, int32_t infmt, int32_t insign, int32_t outfmt, 872 int32_t outsign, int32_t mode) 873{ 874 int sa = 0; 875 int ninvals = SIMD_NVALS[infmt]; 876 int noutvals = SIMD_NVALS[outfmt]; 877 int32_t result; 878 uint64_t in_values[SIMD_MAX_VALS]; 879 uint64_t out_values[SIMD_MAX_VALS]; 880 881 if (insign == SIGNED && outsign == SIGNED) 882 sa = SIMD_NBITS[infmt]; 883 else if (insign == UNSIGNED && outsign == SIGNED) 884 sa = SIMD_NBITS[infmt] - 1; 885 else if (insign == UNSIGNED && outsign == UNSIGNED) 886 sa = 0; 887 888 simdUnpack(a, in_values, infmt, insign); 889 890 for (int i = 0; i<noutvals; i++) { 891 switch (mode) { 892 case MODE_L: 893 out_values[i] = in_values[i + (ninvals >> 1)] << sa; 894 break; 895 case MODE_R: 896 out_values[i] = in_values[i] << sa; 897 break; 898 case MODE_LA: 899 out_values[i] = in_values[(i << 1) + 1] << sa; 900 break; 901 case MODE_RA: 902 out_values[i] = in_values[i << 1] << sa; 903 break; 904 } 905 } 906 907 simdPack(out_values, &result, outfmt); 908 909 return result; 910} 911 912int32_t 913MipsISA::dspPrecrqu(int32_t a, int32_t b, uint32_t *dspctl) 914{ 915 uint64_t a_values[SIMD_MAX_VALS]; 916 uint64_t b_values[SIMD_MAX_VALS]; 917 uint64_t r_values[SIMD_MAX_VALS]; 918 uint32_t ouflag = 0; 919 int32_t result = 0; 920 921 simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED); 922 simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED); 923 924 for (int i = 0; i<2; i++) { 925 r_values[i] = 926 dspSaturate((int64_t)b_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, 927 SIMD_FMT_QB, UNSIGNED, &ouflag); 928 r_values[i + 2] = 929 dspSaturate((int64_t)a_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, 930 SIMD_FMT_QB, UNSIGNED, &ouflag); 931 } 932 933 simdPack(r_values, &result, SIMD_FMT_QB); 934 935 if (ouflag) 936 *dspctl = insertBits(*dspctl, 22, 22, 1); 937 938 return result; 939} 940 941int32_t 942MipsISA::dspPrecrq(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl) 943{ 944 uint64_t a_values[SIMD_MAX_VALS]; 945 uint64_t b_values[SIMD_MAX_VALS]; 946 uint64_t r_values[SIMD_MAX_VALS]; 947 uint32_t ouflag = 0; 948 int32_t result; 949 950 simdUnpack(a, a_values, fmt, SIGNED); 951 simdUnpack(b, b_values, fmt, SIGNED); 952 953 r_values[1] = dspSaturate((int64_t)addHalfLsb(a_values[0], 16) >> 16, 954 fmt + 1, SIGNED, &ouflag); 955 r_values[0] = dspSaturate((int64_t)addHalfLsb(b_values[0], 16) >> 16, 956 fmt + 1, SIGNED, &ouflag); 957 958 simdPack(r_values, &result, fmt + 1); 959 960 if (ouflag) 961 *dspctl = insertBits(*dspctl, 22, 22, 1); 962 963 return result; 964} 965 966int32_t 967MipsISA::dspPrecrSra(int32_t a, int32_t b, int32_t sa, int32_t fmt, 968 int32_t round) 969{ 970 int nvals = SIMD_NVALS[fmt]; 971 uint64_t a_values[SIMD_MAX_VALS]; 972 uint64_t b_values[SIMD_MAX_VALS]; 973 uint64_t c_values[SIMD_MAX_VALS]; 974 int32_t result = 0; 975 976 simdUnpack(a, a_values, fmt, SIGNED); 977 simdUnpack(b, b_values, fmt, SIGNED); 978 979 for (int i = 0; i < nvals; i++) { 980 if (round) { 981 c_values[i] = addHalfLsb(b_values[i], sa) >> sa; 982 c_values[i + 1] = addHalfLsb(a_values[i], sa) >> sa; 983 } else { 984 c_values[i] = b_values[i] >> sa; 985 c_values[i + 1] = a_values[i] >> sa; 986 } 987 } 988 989 simdPack(c_values, &result, fmt + 1); 990 991 return result; 992} 993 994int32_t 995MipsISA::dspPick(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl) 996{ 997 int nvals = SIMD_NVALS[fmt]; 998 int32_t result; 999 uint64_t a_values[SIMD_MAX_VALS]; 1000 uint64_t b_values[SIMD_MAX_VALS]; 1001 uint64_t c_values[SIMD_MAX_VALS]; 1002 1003 simdUnpack(a, a_values, fmt, UNSIGNED); 1004 simdUnpack(b, b_values, fmt, UNSIGNED); 1005 1006 for (int i = 0; i < nvals; i++) { 1007 int condbit = DSP_CTL_POS[DSP_CCOND] + i; 1008 if (bits(*dspctl, condbit, condbit) == 1) 1009 c_values[i] = a_values[i]; 1010 else 1011 c_values[i] = b_values[i]; 1012 } 1013 1014 simdPack(c_values, &result, fmt); 1015 1016 return result; 1017} 1018 1019int32_t 1020MipsISA::dspPack(int32_t a, int32_t b, int32_t fmt) 1021{ 1022 int32_t result; 1023 uint64_t a_values[SIMD_MAX_VALS]; 1024 uint64_t b_values[SIMD_MAX_VALS]; 1025 uint64_t c_values[SIMD_MAX_VALS]; 1026 1027 simdUnpack(a, a_values, fmt, UNSIGNED); 1028 simdUnpack(b, b_values, fmt, UNSIGNED); 1029 1030 c_values[0] = b_values[1]; 1031 c_values[1] = a_values[0]; 1032 1033 simdPack(c_values, &result, fmt); 1034 1035 return result; 1036} 1037 1038int32_t 1039MipsISA::dspExtr(int64_t dspac, int32_t fmt, int32_t sa, int32_t round, 1040 int32_t saturate, uint32_t *dspctl) 1041{ 1042 int32_t result = 0; 1043 uint32_t ouflag = 0; 1044 int64_t temp = 0; 1045 1046 sa = bits(sa, 4, 0); 1047 1048 if (sa > 0) { 1049 if (round) { 1050 temp = (int64_t)addHalfLsb(dspac, sa); 1051 1052 if (dspac > 0 && temp < 0) { 1053 ouflag = 1; 1054 if (saturate) 1055 temp = FIXED_SMAX[SIMD_FMT_L]; 1056 } 1057 temp = temp >> sa; 1058 } else { 1059 temp = dspac >> sa; 1060 } 1061 } else { 1062 temp = dspac; 1063 } 1064 1065 dspac = checkOverflow(dspac, fmt, SIGNED, &ouflag); 1066 1067 if (ouflag) { 1068 *dspctl = insertBits(*dspctl, 23, 23, ouflag); 1069 1070 if (saturate) 1071 result = (int32_t)dspSaturate(temp, fmt, SIGNED, &ouflag); 1072 else 1073 result = (int32_t)temp; 1074 } else { 1075 result = (int32_t)temp; 1076 } 1077 1078 return result; 1079} 1080 1081int32_t 1082MipsISA::dspExtp(int64_t dspac, int32_t size, uint32_t *dspctl) 1083{ 1084 int32_t pos = 0; 1085 int32_t result = 0; 1086 1087 pos = bits(*dspctl, 5, 0); 1088 size = bits(size, 4, 0); 1089 1090 if (pos - (size + 1) >= -1) { 1091 result = bits(dspac, pos, pos - size); 1092 *dspctl = insertBits(*dspctl, 14, 14, 0); 1093 } else { 1094 result = 0; 1095 *dspctl = insertBits(*dspctl, 14, 14, 1); 1096 } 1097 1098 return result; 1099} 1100 1101int32_t 1102MipsISA::dspExtpd(int64_t dspac, int32_t size, uint32_t *dspctl) 1103{ 1104 int32_t pos = 0; 1105 int32_t result = 0; 1106 1107 pos = bits(*dspctl, 5, 0); 1108 size = bits(size, 4, 0); 1109 1110 if (pos - (size + 1) >= -1) { 1111 result = bits(dspac, pos, pos - size); 1112 *dspctl = insertBits(*dspctl, 14, 14, 0); 1113 if (pos - (size + 1) >= 0) 1114 *dspctl = insertBits(*dspctl, 5, 0, pos - (size + 1)); 1115 else if ((pos - (size + 1)) == -1) 1116 *dspctl = insertBits(*dspctl, 5, 0, 63); 1117 } else { 1118 result = 0; 1119 *dspctl = insertBits(*dspctl, 14, 14, 1); 1120 } 1121 1122 return result; 1123} 1124 1125void 1126MipsISA::simdPack(uint64_t *values_ptr, int32_t *reg, int32_t fmt) 1127{ 1128 int nvals = SIMD_NVALS[fmt]; 1129 int nbits = SIMD_NBITS[fmt]; 1130 1131 *reg = 0; 1132 1133 for (int i = 0; i < nvals; i++) 1134 *reg |= (int32_t)bits(values_ptr[i], nbits - 1, 0) << nbits * i; 1135} 1136 1137void 1138MipsISA::simdUnpack(int32_t reg, uint64_t *values_ptr, int32_t fmt, int32_t sign) 1139{ 1140 int nvals = SIMD_NVALS[fmt]; 1141 int nbits = SIMD_NBITS[fmt]; 1142 1143 switch (sign) { 1144 case SIGNED: 1145 for (int i = 0; i < nvals; i++) { 1146 uint64_t tmp = (uint64_t)bits(reg, nbits * (i + 1) - 1, nbits * i); 1147 values_ptr[i] = signExtend(tmp, fmt); 1148 } 1149 break; 1150 case UNSIGNED: 1151 for (int i = 0; i < nvals; i++) { 1152 values_ptr[i] = 1153 (uint64_t)bits(reg, nbits * (i + 1) - 1, nbits * i); 1154 } 1155 break; 1156 } 1157} 1158 1159void 1160MipsISA::writeDSPControl(uint32_t *dspctl, uint32_t value, uint32_t mask) 1161{ 1162 uint32_t fmask = 0; 1163 1164 if (mask & 0x01) fmask |= DSP_CTL_MASK[DSP_POS]; 1165 if (mask & 0x02) fmask |= DSP_CTL_MASK[DSP_SCOUNT]; 1166 if (mask & 0x04) fmask |= DSP_CTL_MASK[DSP_C]; 1167 if (mask & 0x08) fmask |= DSP_CTL_MASK[DSP_OUFLAG]; 1168 if (mask & 0x10) fmask |= DSP_CTL_MASK[DSP_CCOND]; 1169 if (mask & 0x20) fmask |= DSP_CTL_MASK[DSP_EFI]; 1170 1171 *dspctl &= ~fmask; 1172 value &= fmask; 1173 *dspctl |= value; 1174} 1175 1176uint32_t 1177MipsISA::readDSPControl(uint32_t *dspctl, uint32_t mask) 1178{ 1179 uint32_t fmask = 0; 1180 1181 if (mask & 0x01) fmask |= DSP_CTL_MASK[DSP_POS]; 1182 if (mask & 0x02) fmask |= DSP_CTL_MASK[DSP_SCOUNT]; 1183 if (mask & 0x04) fmask |= DSP_CTL_MASK[DSP_C]; 1184 if (mask & 0x08) fmask |= DSP_CTL_MASK[DSP_OUFLAG]; 1185 if (mask & 0x10) fmask |= DSP_CTL_MASK[DSP_CCOND]; 1186 if (mask & 0x20) fmask |= DSP_CTL_MASK[DSP_EFI]; 1187 1188 return *dspctl & fmask; 1189} 1190