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