dsp.cc revision 4661:44458219add1
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