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