style: Remove non-leading tabs everywhere they shouldn't be. Developers should config...
[gem5.git] / src / arch / mips / dsp.cc
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
39 using namespace MipsISA;
40 using namespace std;
41
42 int32_t
43 MipsISA::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
61 uint64_t
62 MipsISA::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
99 uint64_t
100 MipsISA::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
121 uint64_t
122 MipsISA::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
136 uint64_t
137 MipsISA::addHalfLsb( uint64_t value, int32_t lsbpos )
138 {
139 return( value += ULL(1) << (lsbpos-1) );
140 }
141
142 int32_t
143 MipsISA::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
177 int32_t
178 MipsISA::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
206 int32_t
207 MipsISA::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
231 int32_t
232 MipsISA::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
260 int32_t
261 MipsISA::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
285 int32_t
286 MipsISA::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
313 int32_t
314 MipsISA::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
333 int32_t
334 MipsISA::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
358 int32_t
359 MipsISA::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
400 int32_t
401 MipsISA::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
429 int32_t
430 MipsISA::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
462 int32_t
463 MipsISA::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
498 int64_t
499 MipsISA::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
573 int64_t
574 MipsISA::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
648 int64_t
649 MipsISA::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
679 int64_t
680 MipsISA::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
710 int64_t
711 MipsISA::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
757 int64_t
758 MipsISA::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
771 int64_t
772 MipsISA::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
803 void
804 MipsISA::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
832 int32_t
833 MipsISA::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
861 int32_t
862 MipsISA::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
894 int32_t
895 MipsISA::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
930 int32_t
931 MipsISA::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
959 int32_t
960 MipsISA::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
984 int32_t
985 MipsISA::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
1016 int32_t
1017 MipsISA::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
1043 int32_t
1044 MipsISA::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
1062 int32_t
1063 MipsISA::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
1108 int32_t
1109 MipsISA::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
1131 int32_t
1132 MipsISA::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
1158 void
1159 MipsISA::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
1171 void
1172 MipsISA::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
1196 void
1197 MipsISA::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
1213 uint32_t
1214 MipsISA::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 }