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