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