Statistics
| Branch: | Revision:

root / target-mips / dsp_helper.c @ 0ba365f4

History | View | Annotate | Download (135.4 kB)

1
/*
2
 * MIPS ASE DSP Instruction emulation helpers for QEMU.
3
 *
4
 * Copyright (c) 2012  Jia Liu <proljc@gmail.com>
5
 *                     Dongxue Zhang <elta.era@gmail.com>
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19

    
20
#include "cpu.h"
21
#include "helper.h"
22
#include "qemu/bitops.h"
23

    
24
/* As the byte ordering doesn't matter, i.e. all columns are treated
25
   identically, these unions can be used directly.  */
26
typedef union {
27
    uint8_t  ub[4];
28
    int8_t   sb[4];
29
    uint16_t uh[2];
30
    int16_t  sh[2];
31
    uint32_t uw[1];
32
    int32_t  sw[1];
33
} DSP32Value;
34

    
35
typedef union {
36
    uint8_t  ub[8];
37
    int8_t   sb[8];
38
    uint16_t uh[4];
39
    int16_t  sh[4];
40
    uint32_t uw[2];
41
    int32_t  sw[2];
42
    uint64_t ul[1];
43
    int64_t  sl[1];
44
} DSP64Value;
45

    
46
/*** MIPS DSP internal functions begin ***/
47
#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
48
#define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~(a ^ b) & (a ^ c) & d)
49
#define MIPSDSP_OVERFLOW_SUB(a, b, c, d) ((a ^ b) & (a ^ c) & d)
50

    
51
static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
52
                                                CPUMIPSState *env)
53
{
54
    env->active_tc.DSPControl |= (target_ulong)flag << position;
55
}
56

    
57
static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
58
{
59
    env->active_tc.DSPControl |= (target_ulong)flag << 13;
60
}
61

    
62
static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
63
{
64
    return (env->active_tc.DSPControl >> 13) & 0x01;
65
}
66

    
67
static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
68
{
69
  uint32_t filter;
70

    
71
  filter = ((0x01 << len) - 1) << 24;
72
  filter = ~filter;
73

    
74
  env->active_tc.DSPControl &= filter;
75
  env->active_tc.DSPControl |= (target_ulong)flag << 24;
76
}
77

    
78
static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env)
79
{
80
  uint32_t filter;
81

    
82
  filter = (0x01 << len) - 1;
83

    
84
  return (env->active_tc.DSPControl >> 24) & filter;
85
}
86

    
87
static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
88
{
89
    target_ulong dspc;
90

    
91
    dspc = env->active_tc.DSPControl;
92
#ifndef TARGET_MIPS64
93
    dspc = dspc & 0xFFFFFFC0;
94
    dspc |= (pos & 0x3F);
95
#else
96
    dspc = dspc & 0xFFFFFF80;
97
    dspc |= (pos & 0x7F);
98
#endif
99
    env->active_tc.DSPControl = dspc;
100
}
101

    
102
static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
103
{
104
    target_ulong dspc;
105
    uint32_t pos;
106

    
107
    dspc = env->active_tc.DSPControl;
108

    
109
#ifndef TARGET_MIPS64
110
    pos = dspc & 0x3F;
111
#else
112
    pos = dspc & 0x7F;
113
#endif
114

    
115
    return pos;
116
}
117

    
118
static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env)
119
{
120
    env->active_tc.DSPControl &= 0xFFFFBFFF;
121
    env->active_tc.DSPControl |= (target_ulong)flag << 14;
122
}
123

    
124
#define DO_MIPS_SAT_ABS(size)                                          \
125
static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a,         \
126
                                                  CPUMIPSState *env)   \
127
{                                                                      \
128
    if (a == INT##size##_MIN) {                                        \
129
        set_DSPControl_overflow_flag(1, 20, env);                      \
130
        return INT##size##_MAX;                                        \
131
    } else {                                                           \
132
        return MIPSDSP_ABS(a);                                         \
133
    }                                                                  \
134
}
135
DO_MIPS_SAT_ABS(8)
136
DO_MIPS_SAT_ABS(16)
137
DO_MIPS_SAT_ABS(32)
138
#undef DO_MIPS_SAT_ABS
139

    
140
/* get sum value */
141
static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
142
{
143
    int16_t tempI;
144

    
145
    tempI = a + b;
146

    
147
    if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x8000)) {
148
        set_DSPControl_overflow_flag(1, 20, env);
149
    }
150

    
151
    return tempI;
152
}
153

    
154
static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
155
                                          CPUMIPSState *env)
156
{
157
    int16_t tempS;
158

    
159
    tempS = a + b;
160

    
161
    if (MIPSDSP_OVERFLOW_ADD(a, b, tempS, 0x8000)) {
162
        if (a > 0) {
163
            tempS = 0x7FFF;
164
        } else {
165
            tempS = 0x8000;
166
        }
167
        set_DSPControl_overflow_flag(1, 20, env);
168
    }
169

    
170
    return tempS;
171
}
172

    
173
static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
174
                                          CPUMIPSState *env)
175
{
176
    int32_t tempI;
177

    
178
    tempI = a + b;
179

    
180
    if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x80000000)) {
181
        if (a > 0) {
182
            tempI = 0x7FFFFFFF;
183
        } else {
184
            tempI = 0x80000000;
185
        }
186
        set_DSPControl_overflow_flag(1, 20, env);
187
    }
188

    
189
    return tempI;
190
}
191

    
192
static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
193
{
194
    uint16_t temp;
195

    
196
    temp = (uint16_t)a + (uint16_t)b;
197

    
198
    if (temp & 0x0100) {
199
        set_DSPControl_overflow_flag(1, 20, env);
200
    }
201

    
202
    return temp & 0xFF;
203
}
204

    
205
static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b,
206
                                       CPUMIPSState *env)
207
{
208
    uint32_t temp;
209

    
210
    temp = (uint32_t)a + (uint32_t)b;
211

    
212
    if (temp & 0x00010000) {
213
        set_DSPControl_overflow_flag(1, 20, env);
214
    }
215

    
216
    return temp & 0xFFFF;
217
}
218

    
219
static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b,
220
                                         CPUMIPSState *env)
221
{
222
    uint8_t  result;
223
    uint16_t temp;
224

    
225
    temp = (uint16_t)a + (uint16_t)b;
226
    result = temp & 0xFF;
227

    
228
    if (0x0100 & temp) {
229
        result = 0xFF;
230
        set_DSPControl_overflow_flag(1, 20, env);
231
    }
232

    
233
    return result;
234
}
235

    
236
static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b,
237
                                           CPUMIPSState *env)
238
{
239
    uint16_t result;
240
    uint32_t temp;
241

    
242
    temp = (uint32_t)a + (uint32_t)b;
243
    result = temp & 0xFFFF;
244

    
245
    if (0x00010000 & temp) {
246
        result = 0xFFFF;
247
        set_DSPControl_overflow_flag(1, 20, env);
248
    }
249

    
250
    return result;
251
}
252

    
253
static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
254
                                            CPUMIPSState *env)
255
{
256
    int64_t temp;
257
    int32_t temp32, temp31, result;
258
    int64_t temp_sum;
259

    
260
#ifndef TARGET_MIPS64
261
    temp = ((uint64_t)env->active_tc.HI[acc] << 32) |
262
           (uint64_t)env->active_tc.LO[acc];
263
#else
264
    temp = (uint64_t)env->active_tc.LO[acc];
265
#endif
266

    
267
    temp_sum = (int64_t)a + temp;
268

    
269
    temp32 = (temp_sum >> 32) & 0x01;
270
    temp31 = (temp_sum >> 31) & 0x01;
271
    result = temp_sum & 0xFFFFFFFF;
272

    
273
    if (temp32 != temp31) {
274
        if (temp32 == 0) {
275
            result = 0x7FFFFFFF;
276
        } else {
277
            result = 0x80000000;
278
        }
279
        set_DSPControl_overflow_flag(1, 16 + acc, env);
280
    }
281

    
282
    return result;
283
}
284

    
285
/* a[0] is LO, a[1] is HI. */
286
static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
287
                                             int32_t ac,
288
                                             int64_t *a,
289
                                             CPUMIPSState *env)
290
{
291
    bool temp64;
292

    
293
    ret[0] = env->active_tc.LO[ac] + a[0];
294
    ret[1] = env->active_tc.HI[ac] + a[1];
295

    
296
    if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) &&
297
        ((uint64_t)ret[0] < (uint64_t)a[0])) {
298
        ret[1] += 1;
299
    }
300
    temp64 = ret[1] & 1;
301
    if (temp64 != ((ret[0] >> 63) & 0x01)) {
302
        if (temp64) {
303
            ret[0] = (0x01ull << 63);
304
            ret[1] = ~0ull;
305
        } else {
306
            ret[0] = (0x01ull << 63) - 1;
307
            ret[1] = 0x00;
308
        }
309
        set_DSPControl_overflow_flag(1, 16 + ac, env);
310
    }
311
}
312

    
313
static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
314
                                             int32_t ac,
315
                                             int64_t *a,
316
                                             CPUMIPSState *env)
317
{
318
    bool temp64;
319

    
320
    ret[0] = env->active_tc.LO[ac] - a[0];
321
    ret[1] = env->active_tc.HI[ac] - a[1];
322

    
323
    if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) {
324
        ret[1] -= 1;
325
    }
326
    temp64 = ret[1] & 1;
327
    if (temp64 != ((ret[0] >> 63) & 0x01)) {
328
        if (temp64) {
329
            ret[0] = (0x01ull << 63);
330
            ret[1] = ~0ull;
331
        } else {
332
            ret[0] = (0x01ull << 63) - 1;
333
            ret[1] = 0x00;
334
        }
335
        set_DSPControl_overflow_flag(1, 16 + ac, env);
336
    }
337
}
338

    
339
static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
340
                                          CPUMIPSState *env)
341
{
342
    int32_t temp;
343

    
344
    temp = (int32_t)a * (int32_t)b;
345

    
346
    if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) {
347
        set_DSPControl_overflow_flag(1, 21, env);
348
    }
349
    temp &= 0x0000FFFF;
350

    
351
    return temp;
352
}
353

    
354
static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
355
{
356
    return a * b;
357
}
358

    
359
static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
360
{
361
    return a * b;
362
}
363

    
364
static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
365
                                                CPUMIPSState *env)
366
{
367
    int32_t temp;
368

    
369
    temp = (int32_t)a * (int32_t)b;
370

    
371
    if (temp > (int)0x7FFF) {
372
        temp = 0x00007FFF;
373
        set_DSPControl_overflow_flag(1, 21, env);
374
    } else if (temp < (int)0xffff8000) {
375
        temp = 0xFFFF8000;
376
        set_DSPControl_overflow_flag(1, 21, env);
377
    }
378
    temp &= 0x0000FFFF;
379

    
380
    return temp;
381
}
382

    
383
static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b,
384
                                                         CPUMIPSState *env)
385
{
386
    int32_t temp;
387

    
388
    if ((a == 0x8000) && (b == 0x8000)) {
389
        temp = 0x7FFFFFFF;
390
        set_DSPControl_overflow_flag(1, 21, env);
391
    } else {
392
        temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
393
    }
394

    
395
    return temp;
396
}
397

    
398
/* right shift */
399
static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov)
400
{
401
    return a >> mov;
402
}
403

    
404
static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov)
405
{
406
    return a >> mov;
407
}
408

    
409
static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov)
410
{
411
    return a >> mov;
412
}
413

    
414
static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
415
{
416
    return a >> mov;
417
}
418

    
419
static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
420
{
421
    return a >> mov;
422
}
423

    
424
static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
425
{
426
    int32_t temp;
427

    
428
    temp = (int32_t)a + (int32_t)b;
429

    
430
    return (temp >> 1) & 0xFFFF;
431
}
432

    
433
/* round right shift */
434
static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
435
{
436
    int32_t temp;
437

    
438
    temp = (int32_t)a + (int32_t)b;
439
    temp += 1;
440

    
441
    return (temp >> 1) & 0xFFFF;
442
}
443

    
444
static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
445
{
446
    int64_t temp;
447

    
448
    temp = (int64_t)a + (int64_t)b;
449

    
450
    return (temp >> 1) & 0xFFFFFFFF;
451
}
452

    
453
static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
454
{
455
    int64_t temp;
456

    
457
    temp = (int64_t)a + (int64_t)b;
458
    temp += 1;
459

    
460
    return (temp >> 1) & 0xFFFFFFFF;
461
}
462

    
463
static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
464
{
465
    uint16_t temp;
466

    
467
    temp = (uint16_t)a + (uint16_t)b;
468

    
469
    return (temp >> 1) & 0x00FF;
470
}
471

    
472
static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
473
{
474
    uint16_t temp;
475

    
476
    temp = (uint16_t)a + (uint16_t)b + 1;
477

    
478
    return (temp >> 1) & 0x00FF;
479
}
480

    
481
static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
482
{
483
    uint16_t temp;
484

    
485
    temp = (uint16_t)a - (uint16_t)b;
486

    
487
    return (temp >> 1) & 0x00FF;
488
}
489

    
490
static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
491
{
492
    uint16_t temp;
493

    
494
    temp = (uint16_t)a - (uint16_t)b + 1;
495

    
496
    return (temp >> 1) & 0x00FF;
497
}
498

    
499
/*  128 bits long. p[0] is LO, p[1] is HI. */
500
static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
501
                                                int32_t ac,
502
                                                int32_t shift,
503
                                                CPUMIPSState *env)
504
{
505
    int64_t acc;
506

    
507
    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
508
          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
509
    p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1));
510
    p[1] = (acc >> 63) & 0x01;
511
}
512

    
513
/* 128 bits long. p[0] is LO, p[1] is HI */
514
static inline void mipsdsp_rashift_acc(uint64_t *p,
515
                                       uint32_t ac,
516
                                       uint32_t shift,
517
                                       CPUMIPSState *env)
518
{
519
    uint64_t tempB, tempA;
520

    
521
    tempB = env->active_tc.HI[ac];
522
    tempA = env->active_tc.LO[ac];
523
    shift = shift & 0x1F;
524

    
525
    if (shift == 0) {
526
        p[1] = tempB;
527
        p[0] = tempA;
528
    } else {
529
        p[0] = (tempB << (64 - shift)) | (tempA >> shift);
530
        p[1] = (int64_t)tempB >> shift;
531
    }
532
}
533

    
534
/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
535
static inline void mipsdsp_rndrashift_acc(uint64_t *p,
536
                                          uint32_t ac,
537
                                          uint32_t shift,
538
                                          CPUMIPSState *env)
539
{
540
    int64_t tempB, tempA;
541

    
542
    tempB = env->active_tc.HI[ac];
543
    tempA = env->active_tc.LO[ac];
544
    shift = shift & 0x3F;
545

    
546
    if (shift == 0) {
547
        p[2] = tempB >> 63;
548
        p[1] = (tempB << 1) | (tempA >> 63);
549
        p[0] = tempA << 1;
550
    } else {
551
        p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1));
552
        p[1] = (int64_t)tempB >> (shift - 1);
553
        if (tempB >= 0) {
554
            p[2] = 0x0;
555
        } else {
556
            p[2] = ~0ull;
557
        }
558
    }
559
}
560

    
561
static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
562
                                          CPUMIPSState *env)
563
{
564
    int32_t temp;
565

    
566
    if ((a == 0x8000) && (b == 0x8000)) {
567
        temp = 0x7FFFFFFF;
568
        set_DSPControl_overflow_flag(1, 16 + ac, env);
569
    } else {
570
        temp = ((int16_t)a * (int16_t)b) << 1;
571
    }
572

    
573
    return temp;
574
}
575

    
576
static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b,
577
                                          CPUMIPSState *env)
578
{
579
    uint64_t temp;
580

    
581
    if ((a == 0x80000000) && (b == 0x80000000)) {
582
        temp = (0x01ull << 63) - 1;
583
        set_DSPControl_overflow_flag(1, 16 + ac, env);
584
    } else {
585
        temp = ((uint64_t)a * (uint64_t)b) << 1;
586
    }
587

    
588
    return temp;
589
}
590

    
591
static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
592
{
593
    return (uint16_t)a * (uint16_t)b;
594
}
595

    
596
static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
597
                                          CPUMIPSState *env)
598
{
599
    uint32_t tempI;
600

    
601
    tempI = (uint32_t)a * (uint32_t)b;
602
    if (tempI > 0x0000FFFF) {
603
        tempI = 0x0000FFFF;
604
        set_DSPControl_overflow_flag(1, 21, env);
605
    }
606

    
607
    return tempI & 0x0000FFFF;
608
}
609

    
610
static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
611
{
612
    return (uint64_t)a * (uint64_t)b;
613
}
614

    
615
static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
616
                                                 CPUMIPSState *env)
617
{
618
    uint32_t temp;
619

    
620
    if ((a == 0x8000) && (b == 0x8000)) {
621
        temp = 0x7FFF0000;
622
        set_DSPControl_overflow_flag(1, 21, env);
623
    } else {
624
        temp = (a * b) << 1;
625
        temp = temp + 0x00008000;
626
    }
627

    
628
    return (temp & 0xFFFF0000) >> 16;
629
}
630

    
631
static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
632
                                                CPUMIPSState *env)
633
{
634
    int32_t temp;
635

    
636
    if ((a == 0x8000) && (b == 0x8000)) {
637
        temp = 0x7FFF0000;
638
        set_DSPControl_overflow_flag(1, 21, env);
639
    } else {
640
        temp = (int16_t)a * (int16_t)b;
641
        temp = temp << 1;
642
    }
643

    
644
    return (temp >> 16) & 0x0000FFFF;
645
}
646

    
647
static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
648
                                                   CPUMIPSState *env)
649
{
650
    int64_t temp;
651

    
652
    temp = (int32_t)a + 0x00008000;
653

    
654
    if (a > (int)0x7fff8000) {
655
        temp = 0x7FFFFFFF;
656
        set_DSPControl_overflow_flag(1, 22, env);
657
    }
658

    
659
    return (temp >> 16) & 0xFFFF;
660
}
661

    
662
static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
663
                                                    CPUMIPSState *env)
664
{
665
    uint16_t mag;
666
    uint32_t sign;
667

    
668
    sign = (a >> 15) & 0x01;
669
    mag = a & 0x7FFF;
670

    
671
    if (sign == 0) {
672
        if (mag > 0x7F80) {
673
            set_DSPControl_overflow_flag(1, 22, env);
674
            return 0xFF;
675
        } else {
676
            return (mag >> 7) & 0xFFFF;
677
        }
678
    } else {
679
        set_DSPControl_overflow_flag(1, 22, env);
680
        return 0x00;
681
    }
682
}
683

    
684
static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
685
{
686
    uint8_t discard;
687

    
688
    if (s != 0) {
689
        discard = a >> (8 - s);
690

    
691
        if (discard != 0x00) {
692
            set_DSPControl_overflow_flag(1, 22, env);
693
        }
694
    }
695
    return a << s;
696
}
697

    
698
static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
699
                                        CPUMIPSState *env)
700
{
701
    uint16_t discard;
702

    
703
    if (s != 0) {
704
        discard = (int16_t)a >> (15 - s);
705

    
706
        if ((discard != 0x0000) && (discard != 0xFFFF)) {
707
            set_DSPControl_overflow_flag(1, 22, env);
708
        }
709
    }
710
    return a << s;
711
}
712

    
713

    
714
static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
715
                                        CPUMIPSState *env)
716
{
717
    uint32_t discard;
718

    
719
    if (s == 0) {
720
        return a;
721
    } else {
722
        discard = (int32_t)a >> (31 - (s - 1));
723

    
724
        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
725
            set_DSPControl_overflow_flag(1, 22, env);
726
        }
727
        return a << s;
728
    }
729
}
730

    
731
static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
732
                                            CPUMIPSState *env)
733
{
734
    uint8_t  sign;
735
    uint16_t discard;
736

    
737
    if (s == 0) {
738
        return a;
739
    } else {
740
        sign = (a >> 15) & 0x01;
741
        if (sign != 0) {
742
            discard = (((0x01 << (16 - s)) - 1) << s) |
743
                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
744
        } else {
745
            discard = a >> (14 - (s - 1));
746
        }
747

    
748
        if ((discard != 0x0000) && (discard != 0xFFFF)) {
749
            set_DSPControl_overflow_flag(1, 22, env);
750
            return (sign == 0) ? 0x7FFF : 0x8000;
751
        } else {
752
            return a << s;
753
        }
754
    }
755
}
756

    
757
static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s,
758
                                            CPUMIPSState *env)
759
{
760
    uint8_t  sign;
761
    uint32_t discard;
762

    
763
    if (s == 0) {
764
        return a;
765
    } else {
766
        sign = (a >> 31) & 0x01;
767
        if (sign != 0) {
768
            discard = (((0x01 << (32 - s)) - 1) << s) |
769
                      ((a >> (30 - (s - 1))) & ((0x01 << s) - 1));
770
        } else {
771
            discard = a >> (30 - (s - 1));
772
        }
773

    
774
        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
775
            set_DSPControl_overflow_flag(1, 22, env);
776
            return (sign == 0) ? 0x7FFFFFFF : 0x80000000;
777
        } else {
778
            return a << s;
779
        }
780
    }
781
}
782

    
783
static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s)
784
{
785
    uint32_t temp;
786

    
787
    if (s == 0) {
788
        temp = (uint32_t)a << 1;
789
    } else {
790
        temp = (int32_t)(int8_t)a >> (s - 1);
791
    }
792

    
793
    return (temp + 1) >> 1;
794
}
795

    
796
static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
797
{
798
    uint32_t temp;
799

    
800
    if (s == 0) {
801
        temp = (uint32_t)a << 1;
802
    } else {
803
        temp = (int32_t)(int16_t)a >> (s - 1);
804
    }
805

    
806
    return (temp + 1) >> 1;
807
}
808

    
809
static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
810
{
811
    int64_t temp;
812

    
813
    if (s == 0) {
814
        temp = (uint64_t)a << 1;
815
    } else {
816
        temp = (int64_t)(int32_t)a >> (s - 1);
817
    }
818
    temp += 1;
819

    
820
    return (temp >> 1) & 0xFFFFFFFFull;
821
}
822

    
823
static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
824
{
825
    int16_t  temp;
826

    
827
    temp = a - b;
828
    if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
829
        set_DSPControl_overflow_flag(1, 20, env);
830
    }
831

    
832
    return temp;
833
}
834

    
835
static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
836
                                         CPUMIPSState *env)
837
{
838
    int16_t  temp;
839

    
840
    temp = a - b;
841
    if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
842
        if (a >= 0) {
843
            temp = 0x7FFF;
844
        } else {
845
            temp = 0x8000;
846
        }
847
        set_DSPControl_overflow_flag(1, 20, env);
848
    }
849

    
850
    return temp;
851
}
852

    
853
static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
854
                                         CPUMIPSState *env)
855
{
856
    int32_t  temp;
857

    
858
    temp = a - b;
859
    if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
860
        if (a >= 0) {
861
            temp = 0x7FFFFFFF;
862
        } else {
863
            temp = 0x80000000;
864
        }
865
        set_DSPControl_overflow_flag(1, 20, env);
866
    }
867

    
868
    return temp & 0xFFFFFFFFull;
869
}
870

    
871
static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
872
{
873
    int32_t  temp;
874

    
875
    temp = (int32_t)a - (int32_t)b;
876

    
877
    return (temp >> 1) & 0x0000FFFF;
878
}
879

    
880
static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
881
{
882
    int32_t  temp;
883

    
884
    temp = (int32_t)a - (int32_t)b;
885
    temp += 1;
886

    
887
    return (temp >> 1) & 0x0000FFFF;
888
}
889

    
890
static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
891
{
892
    int64_t  temp;
893

    
894
    temp = (int64_t)a - (int64_t)b;
895

    
896
    return (temp >> 1) & 0xFFFFFFFFull;
897
}
898

    
899
static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
900
{
901
    int64_t  temp;
902

    
903
    temp = (int64_t)a - (int64_t)b;
904
    temp += 1;
905

    
906
    return (temp >> 1) & 0xFFFFFFFFull;
907
}
908

    
909
static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b,
910
                                           CPUMIPSState *env)
911
{
912
    uint8_t  temp16;
913
    uint32_t temp;
914

    
915
    temp = (uint32_t)a - (uint32_t)b;
916
    temp16 = (temp >> 16) & 0x01;
917
    if (temp16 == 1) {
918
        set_DSPControl_overflow_flag(1, 20, env);
919
    }
920
    return temp & 0x0000FFFF;
921
}
922

    
923
static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b,
924
                                                  CPUMIPSState *env)
925
{
926
    uint8_t  temp16;
927
    uint32_t temp;
928

    
929
    temp   = (uint32_t)a - (uint32_t)b;
930
    temp16 = (temp >> 16) & 0x01;
931

    
932
    if (temp16 == 1) {
933
        temp = 0x0000;
934
        set_DSPControl_overflow_flag(1, 20, env);
935
    }
936

    
937
    return temp & 0x0000FFFF;
938
}
939

    
940
static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
941
{
942
    uint8_t  temp8;
943
    uint16_t temp;
944

    
945
    temp = (uint16_t)a - (uint16_t)b;
946
    temp8 = (temp >> 8) & 0x01;
947
    if (temp8 == 1) {
948
        set_DSPControl_overflow_flag(1, 20, env);
949
    }
950

    
951
    return temp & 0x00FF;
952
}
953

    
954
static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
955
{
956
    uint8_t  temp8;
957
    uint16_t temp;
958

    
959
    temp = (uint16_t)a - (uint16_t)b;
960
    temp8 = (temp >> 8) & 0x01;
961
    if (temp8 == 1) {
962
        temp = 0x00;
963
        set_DSPControl_overflow_flag(1, 20, env);
964
    }
965

    
966
    return temp & 0x00FF;
967
}
968

    
969
static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
970
{
971
    int32_t temp;
972

    
973
    temp = a - b;
974
    if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
975
        set_DSPControl_overflow_flag(1, 20, env);
976
    }
977

    
978
    return temp;
979
}
980

    
981
static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
982
{
983
    int32_t temp;
984

    
985
    temp = a + b;
986

    
987
    if (MIPSDSP_OVERFLOW_ADD(a, b, temp, 0x80000000)) {
988
        set_DSPControl_overflow_flag(1, 20, env);
989
    }
990

    
991
    return temp;
992
}
993

    
994
static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b)
995
{
996
    return a == b;
997
}
998

    
999
static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b)
1000
{
1001
    return a <= b;
1002
}
1003

    
1004
static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b)
1005
{
1006
    return a < b;
1007
}
1008

    
1009
static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b)
1010
{
1011
    return a == b;
1012
}
1013

    
1014
static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b)
1015
{
1016
    return a <= b;
1017
}
1018

    
1019
static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
1020
{
1021
    return a < b;
1022
}
1023
/*** MIPS DSP internal functions end ***/
1024

    
1025
#define MIPSDSP_LHI 0xFFFFFFFF00000000ull
1026
#define MIPSDSP_LLO 0x00000000FFFFFFFFull
1027
#define MIPSDSP_HI  0xFFFF0000
1028
#define MIPSDSP_LO  0x0000FFFF
1029
#define MIPSDSP_Q3  0xFF000000
1030
#define MIPSDSP_Q2  0x00FF0000
1031
#define MIPSDSP_Q1  0x0000FF00
1032
#define MIPSDSP_Q0  0x000000FF
1033

    
1034
#define MIPSDSP_SPLIT32_8(num, a, b, c, d)  \
1035
    do {                                    \
1036
        a = (num >> 24) & MIPSDSP_Q0;       \
1037
        b = (num >> 16) & MIPSDSP_Q0;       \
1038
        c = (num >> 8) & MIPSDSP_Q0;        \
1039
        d = num & MIPSDSP_Q0;               \
1040
    } while (0)
1041

    
1042
#define MIPSDSP_SPLIT32_16(num, a, b)       \
1043
    do {                                    \
1044
        a = (num >> 16) & MIPSDSP_LO;       \
1045
        b = num & MIPSDSP_LO;               \
1046
    } while (0)
1047

    
1048
#define MIPSDSP_RETURN32_8(a, b, c, d)  ((target_long)(int32_t) \
1049
                                         (((uint32_t)a << 24) | \
1050
                                         (((uint32_t)b << 16) | \
1051
                                         (((uint32_t)c << 8) |  \
1052
                                          ((uint32_t)d & 0xFF)))))
1053
#define MIPSDSP_RETURN32_16(a, b)       ((target_long)(int32_t) \
1054
                                         (((uint32_t)a << 16) | \
1055
                                          ((uint32_t)b & 0xFFFF)))
1056

    
1057
#ifdef TARGET_MIPS64
1058
#define MIPSDSP_SPLIT64_16(num, a, b, c, d)  \
1059
    do {                                     \
1060
        a = (num >> 48) & MIPSDSP_LO;        \
1061
        b = (num >> 32) & MIPSDSP_LO;        \
1062
        c = (num >> 16) & MIPSDSP_LO;        \
1063
        d = num & MIPSDSP_LO;                \
1064
    } while (0)
1065

    
1066
#define MIPSDSP_SPLIT64_32(num, a, b)       \
1067
    do {                                    \
1068
        a = (num >> 32) & MIPSDSP_LLO;      \
1069
        b = num & MIPSDSP_LLO;              \
1070
    } while (0)
1071

    
1072
#define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
1073
                                         ((uint64_t)b << 32) | \
1074
                                         ((uint64_t)c << 16) | \
1075
                                         (uint64_t)d)
1076
#define MIPSDSP_RETURN64_32(a, b)       (((uint64_t)a << 32) | (uint64_t)b)
1077
#endif
1078

    
1079
/** DSP Arithmetic Sub-class insns **/
1080
#define MIPSDSP32_UNOP_ENV(name, func, element)                            \
1081
target_ulong helper_##name(target_ulong rt, CPUMIPSState *env)             \
1082
{                                                                          \
1083
    DSP32Value dt;                                                         \
1084
    unsigned int i, n;                                                     \
1085
                                                                           \
1086
    n = sizeof(DSP32Value) / sizeof(dt.element[0]);                        \
1087
    dt.sw[0] = rt;                                                         \
1088
                                                                           \
1089
    for (i = 0; i < n; i++) {                                              \
1090
        dt.element[i] = mipsdsp_##func(dt.element[i], env);                \
1091
    }                                                                      \
1092
                                                                           \
1093
    return (target_long)dt.sw[0];                                          \
1094
}
1095
MIPSDSP32_UNOP_ENV(absq_s_ph, sat_abs16, sh)
1096
MIPSDSP32_UNOP_ENV(absq_s_qb, sat_abs8, sb)
1097
MIPSDSP32_UNOP_ENV(absq_s_w, sat_abs32, sw)
1098
#undef MIPSDSP32_UNOP_ENV
1099

    
1100
#if defined(TARGET_MIPS64)
1101
#define MIPSDSP64_UNOP_ENV(name, func, element)                            \
1102
target_ulong helper_##name(target_ulong rt, CPUMIPSState *env)             \
1103
{                                                                          \
1104
    DSP64Value dt;                                                         \
1105
    unsigned int i, n;                                                     \
1106
                                                                           \
1107
    n = sizeof(DSP64Value) / sizeof(dt.element[0]);                        \
1108
    dt.sl[0] = rt;                                                         \
1109
                                                                           \
1110
    for (i = 0; i < n; i++) {                                              \
1111
        dt.element[i] = mipsdsp_##func(dt.element[i], env);                \
1112
    }                                                                      \
1113
                                                                           \
1114
    return dt.sl[0];                                                       \
1115
}
1116
MIPSDSP64_UNOP_ENV(absq_s_ob, sat_abs8, sb)
1117
MIPSDSP64_UNOP_ENV(absq_s_qh, sat_abs16, sh)
1118
MIPSDSP64_UNOP_ENV(absq_s_pw, sat_abs32, sw)
1119
#undef MIPSDSP64_UNOP_ENV
1120
#endif
1121

    
1122
#define MIPSDSP32_BINOP(name, func, element)                               \
1123
target_ulong helper_##name(target_ulong rs, target_ulong rt)               \
1124
{                                                                          \
1125
    DSP32Value ds, dt;                                                     \
1126
    unsigned int i, n;                                                     \
1127
                                                                           \
1128
    n = sizeof(DSP32Value) / sizeof(ds.element[0]);                        \
1129
    ds.sw[0] = rs;                                                         \
1130
    dt.sw[0] = rt;                                                         \
1131
                                                                           \
1132
    for (i = 0; i < n; i++) {                                              \
1133
        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]);      \
1134
    }                                                                      \
1135
                                                                           \
1136
    return (target_long)ds.sw[0];                                          \
1137
}
1138
MIPSDSP32_BINOP(addqh_ph, rshift1_add_q16, sh);
1139
MIPSDSP32_BINOP(addqh_r_ph, rrshift1_add_q16, sh);
1140
MIPSDSP32_BINOP(addqh_r_w, rrshift1_add_q32, sw);
1141
MIPSDSP32_BINOP(addqh_w, rshift1_add_q32, sw);
1142
MIPSDSP32_BINOP(adduh_qb, rshift1_add_u8, ub);
1143
MIPSDSP32_BINOP(adduh_r_qb, rrshift1_add_u8, ub);
1144
MIPSDSP32_BINOP(subqh_ph, rshift1_sub_q16, sh);
1145
MIPSDSP32_BINOP(subqh_r_ph, rrshift1_sub_q16, sh);
1146
MIPSDSP32_BINOP(subqh_r_w, rrshift1_sub_q32, sw);
1147
MIPSDSP32_BINOP(subqh_w, rshift1_sub_q32, sw);
1148
#undef MIPSDSP32_BINOP
1149

    
1150
#define MIPSDSP32_BINOP_ENV(name, func, element)                           \
1151
target_ulong helper_##name(target_ulong rs, target_ulong rt,               \
1152
                           CPUMIPSState *env)                              \
1153
{                                                                          \
1154
    DSP32Value ds, dt;                                                     \
1155
    unsigned int i, n;                                                     \
1156
                                                                           \
1157
    n = sizeof(DSP32Value) / sizeof(ds.element[0]);                        \
1158
    ds.sw[0] = rs;                                                         \
1159
    dt.sw[0] = rt;                                                         \
1160
                                                                           \
1161
    for (i = 0 ; i < n ; i++) {                                            \
1162
        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
1163
    }                                                                      \
1164
                                                                           \
1165
    return (target_long)ds.sw[0];                                          \
1166
}
1167
MIPSDSP32_BINOP_ENV(addq_ph, add_i16, sh)
1168
MIPSDSP32_BINOP_ENV(addq_s_ph, sat_add_i16, sh)
1169
MIPSDSP32_BINOP_ENV(addq_s_w, sat_add_i32, sw);
1170
MIPSDSP32_BINOP_ENV(addu_ph, add_u16, sh)
1171
MIPSDSP32_BINOP_ENV(addu_qb, add_u8, ub);
1172
MIPSDSP32_BINOP_ENV(addu_s_ph, sat_add_u16, sh)
1173
MIPSDSP32_BINOP_ENV(addu_s_qb, sat_add_u8, ub);
1174
MIPSDSP32_BINOP_ENV(subq_ph, sub_i16, sh);
1175
MIPSDSP32_BINOP_ENV(subq_s_ph, sat16_sub, sh);
1176
MIPSDSP32_BINOP_ENV(subq_s_w, sat32_sub, sw);
1177
MIPSDSP32_BINOP_ENV(subu_ph, sub_u16_u16, sh);
1178
MIPSDSP32_BINOP_ENV(subu_qb, sub_u8, ub);
1179
MIPSDSP32_BINOP_ENV(subu_s_ph, satu16_sub_u16_u16, sh);
1180
MIPSDSP32_BINOP_ENV(subu_s_qb, satu8_sub, ub);
1181
#undef MIPSDSP32_BINOP_ENV
1182

    
1183
#ifdef TARGET_MIPS64
1184
#define MIPSDSP64_BINOP(name, func, element)                               \
1185
target_ulong helper_##name(target_ulong rs, target_ulong rt)               \
1186
{                                                                          \
1187
    DSP64Value ds, dt;                                                     \
1188
    unsigned int i, n;                                                     \
1189
                                                                           \
1190
    n = sizeof(DSP64Value) / sizeof(ds.element[0]);                        \
1191
    ds.sl[0] = rs;                                                         \
1192
    dt.sl[0] = rt;                                                         \
1193
                                                                           \
1194
    for (i = 0 ; i < n ; i++) {                                            \
1195
        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]);      \
1196
    }                                                                      \
1197
                                                                           \
1198
    return ds.sl[0];                                                       \
1199
}
1200
MIPSDSP64_BINOP(adduh_ob, rshift1_add_u8, ub);
1201
MIPSDSP64_BINOP(adduh_r_ob, rrshift1_add_u8, ub);
1202
MIPSDSP64_BINOP(subuh_ob, rshift1_sub_u8, ub);
1203
MIPSDSP64_BINOP(subuh_r_ob, rrshift1_sub_u8, ub);
1204
#undef MIPSDSP64_BINOP
1205

    
1206
#define MIPSDSP64_BINOP_ENV(name, func, element)                           \
1207
target_ulong helper_##name(target_ulong rs, target_ulong rt,               \
1208
                           CPUMIPSState *env)                              \
1209
{                                                                          \
1210
    DSP64Value ds, dt;                                                     \
1211
    unsigned int i, n;                                                     \
1212
                                                                           \
1213
    n = sizeof(DSP64Value) / sizeof(ds.element[0]);                        \
1214
    ds.sl[0] = rs;                                                         \
1215
    dt.sl[0] = rt;                                                         \
1216
                                                                           \
1217
    for (i = 0 ; i < n ; i++) {                                            \
1218
        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
1219
    }                                                                      \
1220
                                                                           \
1221
    return ds.sl[0];                                                       \
1222
}
1223
MIPSDSP64_BINOP_ENV(addq_pw, add_i32, sw);
1224
MIPSDSP64_BINOP_ENV(addq_qh, add_i16, sh);
1225
MIPSDSP64_BINOP_ENV(addq_s_pw, sat_add_i32, sw);
1226
MIPSDSP64_BINOP_ENV(addq_s_qh, sat_add_i16, sh);
1227
MIPSDSP64_BINOP_ENV(addu_ob, add_u8, uh);
1228
MIPSDSP64_BINOP_ENV(addu_qh, add_u16, uh);
1229
MIPSDSP64_BINOP_ENV(addu_s_ob, sat_add_u8, uh);
1230
MIPSDSP64_BINOP_ENV(addu_s_qh, sat_add_u16, uh);
1231
MIPSDSP64_BINOP_ENV(subq_pw, sub32, sw);
1232
MIPSDSP64_BINOP_ENV(subq_qh, sub_i16, sh);
1233
MIPSDSP64_BINOP_ENV(subq_s_pw, sat32_sub, sw);
1234
MIPSDSP64_BINOP_ENV(subq_s_qh, sat16_sub, sh);
1235
MIPSDSP64_BINOP_ENV(subu_ob, sub_u8, uh);
1236
MIPSDSP64_BINOP_ENV(subu_qh, sub_u16_u16, uh);
1237
MIPSDSP64_BINOP_ENV(subu_s_ob, satu8_sub, uh);
1238
MIPSDSP64_BINOP_ENV(subu_s_qh, satu16_sub_u16_u16, uh);
1239
#undef MIPSDSP64_BINOP_ENV
1240

    
1241
#endif
1242

    
1243
#define SUBUH_QB(name, var) \
1244
target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
1245
{                                                                 \
1246
    uint8_t rs3, rs2, rs1, rs0;                                   \
1247
    uint8_t rt3, rt2, rt1, rt0;                                   \
1248
    uint8_t tempD, tempC, tempB, tempA;                           \
1249
                                                                  \
1250
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
1251
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
1252
                                                                  \
1253
    tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1;           \
1254
    tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1;           \
1255
    tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1;           \
1256
    tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1;           \
1257
                                                                  \
1258
    return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |    \
1259
        ((uint32_t)tempB << 8) | ((uint32_t)tempA);               \
1260
}
1261

    
1262
SUBUH_QB(subuh, 0);
1263
SUBUH_QB(subuh_r, 1);
1264

    
1265
#undef SUBUH_QB
1266

    
1267
target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1268
{
1269
    uint64_t temp, tempRs, tempRt;
1270
    int32_t flag;
1271

    
1272
    tempRs = (uint64_t)rs & MIPSDSP_LLO;
1273
    tempRt = (uint64_t)rt & MIPSDSP_LLO;
1274

    
1275
    temp = tempRs + tempRt;
1276
    flag = (temp & 0x0100000000ull) >> 32;
1277
    set_DSPControl_carryflag(flag, env);
1278

    
1279
    return (target_long)(int32_t)(temp & MIPSDSP_LLO);
1280
}
1281

    
1282
target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1283
{
1284
    uint32_t rd;
1285
    int32_t temp32, temp31;
1286
    int64_t tempL;
1287

    
1288
    tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt +
1289
        get_DSPControl_carryflag(env);
1290
    temp31 = (tempL >> 31) & 0x01;
1291
    temp32 = (tempL >> 32) & 0x01;
1292

    
1293
    if (temp31 != temp32) {
1294
        set_DSPControl_overflow_flag(1, 20, env);
1295
    }
1296

    
1297
    rd = tempL & MIPSDSP_LLO;
1298

    
1299
    return (target_long)(int32_t)rd;
1300
}
1301

    
1302
target_ulong helper_modsub(target_ulong rs, target_ulong rt)
1303
{
1304
    int32_t decr;
1305
    uint16_t lastindex;
1306
    target_ulong rd;
1307

    
1308
    decr = rt & MIPSDSP_Q0;
1309
    lastindex = (rt >> 8) & MIPSDSP_LO;
1310

    
1311
    if ((rs & MIPSDSP_LLO) == 0x00000000) {
1312
        rd = (target_ulong)lastindex;
1313
    } else {
1314
        rd = rs - decr;
1315
    }
1316

    
1317
    return rd;
1318
}
1319

    
1320
target_ulong helper_raddu_w_qb(target_ulong rs)
1321
{
1322
    target_ulong ret = 0;
1323
    DSP32Value ds;
1324
    unsigned int i;
1325

    
1326
    ds.uw[0] = rs;
1327
    for (i = 0; i < 4; i++) {
1328
        ret += ds.ub[i];
1329
    }
1330
    return ret;
1331
}
1332

    
1333
#if defined(TARGET_MIPS64)
1334
target_ulong helper_raddu_l_ob(target_ulong rs)
1335
{
1336
    target_ulong ret = 0;
1337
    DSP64Value ds;
1338
    unsigned int i;
1339

    
1340
    ds.ul[0] = rs;
1341
    for (i = 0; i < 8; i++) {
1342
        ret += ds.ub[i];
1343
    }
1344
    return ret;
1345
}
1346
#endif
1347

    
1348
#define PRECR_QB_PH(name, a, b)\
1349
target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \
1350
{                                                                    \
1351
    uint8_t tempD, tempC, tempB, tempA;                              \
1352
                                                                     \
1353
    tempD = (rs >> a) & MIPSDSP_Q0;                                  \
1354
    tempC = (rs >> b) & MIPSDSP_Q0;                                  \
1355
    tempB = (rt >> a) & MIPSDSP_Q0;                                  \
1356
    tempA = (rt >> b) & MIPSDSP_Q0;                                  \
1357
                                                                     \
1358
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);           \
1359
}
1360

    
1361
PRECR_QB_PH(precr, 16, 0);
1362
PRECR_QB_PH(precrq, 24, 8);
1363

    
1364
#undef PRECR_QB_OH
1365

    
1366
target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
1367
                                   target_ulong rt)
1368
{
1369
    uint16_t tempB, tempA;
1370

    
1371
    tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
1372
    tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
1373

    
1374
    return MIPSDSP_RETURN32_16(tempB, tempA);
1375
}
1376

    
1377
target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
1378
                                     target_ulong rs, target_ulong rt)
1379
{
1380
    uint64_t tempB, tempA;
1381

    
1382
    /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */
1383
    if (sa == 0) {
1384
        tempB = (rt & MIPSDSP_LO) << 1;
1385
        tempA = (rs & MIPSDSP_LO) << 1;
1386
    } else {
1387
        tempB = ((int32_t)rt >> (sa - 1)) + 1;
1388
        tempA = ((int32_t)rs >> (sa - 1)) + 1;
1389
    }
1390
    rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
1391

    
1392
    return (target_long)(int32_t)rt;
1393
}
1394

    
1395
target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
1396
{
1397
    uint16_t tempB, tempA;
1398

    
1399
    tempB = (rs & MIPSDSP_HI) >> 16;
1400
    tempA = (rt & MIPSDSP_HI) >> 16;
1401

    
1402
    return MIPSDSP_RETURN32_16(tempB, tempA);
1403
}
1404

    
1405
target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt,
1406
                                   CPUMIPSState *env)
1407
{
1408
    uint16_t tempB, tempA;
1409

    
1410
    tempB = mipsdsp_trunc16_sat16_round(rs, env);
1411
    tempA = mipsdsp_trunc16_sat16_round(rt, env);
1412

    
1413
    return MIPSDSP_RETURN32_16(tempB, tempA);
1414
}
1415

    
1416
#if defined(TARGET_MIPS64)
1417
target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
1418
{
1419
    uint8_t rs6, rs4, rs2, rs0;
1420
    uint8_t rt6, rt4, rt2, rt0;
1421
    uint64_t temp;
1422

    
1423
    rs6 = (rs >> 48) & MIPSDSP_Q0;
1424
    rs4 = (rs >> 32) & MIPSDSP_Q0;
1425
    rs2 = (rs >> 16) & MIPSDSP_Q0;
1426
    rs0 = rs & MIPSDSP_Q0;
1427
    rt6 = (rt >> 48) & MIPSDSP_Q0;
1428
    rt4 = (rt >> 32) & MIPSDSP_Q0;
1429
    rt2 = (rt >> 16) & MIPSDSP_Q0;
1430
    rt0 = rt & MIPSDSP_Q0;
1431

    
1432
    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1433
           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1434
           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1435
           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1436

    
1437
    return temp;
1438
}
1439

    
1440
#define PRECR_QH_PW(name, var) \
1441
target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \
1442
                                    uint32_t sa)                      \
1443
{                                                                     \
1444
    uint16_t rs3, rs2, rs1, rs0;                                      \
1445
    uint16_t rt3, rt2, rt1, rt0;                                      \
1446
    uint16_t tempD, tempC, tempB, tempA;                              \
1447
                                                                      \
1448
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                       \
1449
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                       \
1450
                                                                      \
1451
    /* When sa = 0, we use rt2, rt0, rs2, rs0;                        \
1452
     * when sa != 0, we use rt3, rt1, rs3, rs1. */                    \
1453
    if (sa == 0) {                                                    \
1454
        tempD = rt2 << var;                                           \
1455
        tempC = rt0 << var;                                           \
1456
        tempB = rs2 << var;                                           \
1457
        tempA = rs0 << var;                                           \
1458
    } else {                                                          \
1459
        tempD = (((int16_t)rt3 >> sa) + var) >> var;                  \
1460
        tempC = (((int16_t)rt1 >> sa) + var) >> var;                  \
1461
        tempB = (((int16_t)rs3 >> sa) + var) >> var;                  \
1462
        tempA = (((int16_t)rs1 >> sa) + var) >> var;                  \
1463
    }                                                                 \
1464
                                                                      \
1465
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);           \
1466
}
1467

    
1468
PRECR_QH_PW(sra, 0);
1469
PRECR_QH_PW(sra_r, 1);
1470

    
1471
#undef PRECR_QH_PW
1472

    
1473
target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
1474
{
1475
    uint8_t rs6, rs4, rs2, rs0;
1476
    uint8_t rt6, rt4, rt2, rt0;
1477
    uint64_t temp;
1478

    
1479
    rs6 = (rs >> 56) & MIPSDSP_Q0;
1480
    rs4 = (rs >> 40) & MIPSDSP_Q0;
1481
    rs2 = (rs >> 24) & MIPSDSP_Q0;
1482
    rs0 = (rs >> 8) & MIPSDSP_Q0;
1483
    rt6 = (rt >> 56) & MIPSDSP_Q0;
1484
    rt4 = (rt >> 40) & MIPSDSP_Q0;
1485
    rt2 = (rt >> 24) & MIPSDSP_Q0;
1486
    rt0 = (rt >> 8) & MIPSDSP_Q0;
1487

    
1488
    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1489
           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1490
           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1491
           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1492

    
1493
    return temp;
1494
}
1495

    
1496
target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
1497
{
1498
    uint16_t tempD, tempC, tempB, tempA;
1499

    
1500
    tempD = (rs >> 48) & MIPSDSP_LO;
1501
    tempC = (rs >> 16) & MIPSDSP_LO;
1502
    tempB = (rt >> 48) & MIPSDSP_LO;
1503
    tempA = (rt >> 16) & MIPSDSP_LO;
1504

    
1505
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1506
}
1507

    
1508
target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt,
1509
                                    CPUMIPSState *env)
1510
{
1511
    uint32_t rs2, rs0;
1512
    uint32_t rt2, rt0;
1513
    uint16_t tempD, tempC, tempB, tempA;
1514

    
1515
    rs2 = (rs >> 32) & MIPSDSP_LLO;
1516
    rs0 = rs & MIPSDSP_LLO;
1517
    rt2 = (rt >> 32) & MIPSDSP_LLO;
1518
    rt0 = rt & MIPSDSP_LLO;
1519

    
1520
    tempD = mipsdsp_trunc16_sat16_round(rs2, env);
1521
    tempC = mipsdsp_trunc16_sat16_round(rs0, env);
1522
    tempB = mipsdsp_trunc16_sat16_round(rt2, env);
1523
    tempA = mipsdsp_trunc16_sat16_round(rt0, env);
1524

    
1525
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1526
}
1527

    
1528
target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
1529
{
1530
    uint32_t tempB, tempA;
1531

    
1532
    tempB = (rs >> 32) & MIPSDSP_LLO;
1533
    tempA = (rt >> 32) & MIPSDSP_LLO;
1534

    
1535
    return MIPSDSP_RETURN64_32(tempB, tempA);
1536
}
1537
#endif
1538

    
1539
target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt,
1540
                                    CPUMIPSState *env)
1541
{
1542
    uint8_t  tempD, tempC, tempB, tempA;
1543
    uint16_t rsh, rsl, rth, rtl;
1544

    
1545
    rsh = (rs & MIPSDSP_HI) >> 16;
1546
    rsl =  rs & MIPSDSP_LO;
1547
    rth = (rt & MIPSDSP_HI) >> 16;
1548
    rtl =  rt & MIPSDSP_LO;
1549

    
1550
    tempD = mipsdsp_sat8_reduce_precision(rsh, env);
1551
    tempC = mipsdsp_sat8_reduce_precision(rsl, env);
1552
    tempB = mipsdsp_sat8_reduce_precision(rth, env);
1553
    tempA = mipsdsp_sat8_reduce_precision(rtl, env);
1554

    
1555
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
1556
}
1557

    
1558
#if defined(TARGET_MIPS64)
1559
target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt,
1560
                                    CPUMIPSState *env)
1561
{
1562
    int i;
1563
    uint16_t rs3, rs2, rs1, rs0;
1564
    uint16_t rt3, rt2, rt1, rt0;
1565
    uint8_t temp[8];
1566
    uint64_t result;
1567

    
1568
    result = 0;
1569

    
1570
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
1571
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
1572

    
1573
    temp[7] = mipsdsp_sat8_reduce_precision(rs3, env);
1574
    temp[6] = mipsdsp_sat8_reduce_precision(rs2, env);
1575
    temp[5] = mipsdsp_sat8_reduce_precision(rs1, env);
1576
    temp[4] = mipsdsp_sat8_reduce_precision(rs0, env);
1577
    temp[3] = mipsdsp_sat8_reduce_precision(rt3, env);
1578
    temp[2] = mipsdsp_sat8_reduce_precision(rt2, env);
1579
    temp[1] = mipsdsp_sat8_reduce_precision(rt1, env);
1580
    temp[0] = mipsdsp_sat8_reduce_precision(rt0, env);
1581

    
1582
    for (i = 0; i < 8; i++) {
1583
        result |= (uint64_t)temp[i] << (8 * i);
1584
    }
1585

    
1586
    return result;
1587
}
1588

    
1589
#define PRECEQ_PW(name, a, b) \
1590
target_ulong helper_preceq_pw_##name(target_ulong rt) \
1591
{                                                       \
1592
    uint16_t tempB, tempA;                              \
1593
    uint32_t tempBI, tempAI;                            \
1594
                                                        \
1595
    tempB = (rt >> a) & MIPSDSP_LO;                     \
1596
    tempA = (rt >> b) & MIPSDSP_LO;                     \
1597
                                                        \
1598
    tempBI = (uint32_t)tempB << 16;                     \
1599
    tempAI = (uint32_t)tempA << 16;                     \
1600
                                                        \
1601
    return MIPSDSP_RETURN64_32(tempBI, tempAI);         \
1602
}
1603

    
1604
PRECEQ_PW(qhl, 48, 32);
1605
PRECEQ_PW(qhr, 16, 0);
1606
PRECEQ_PW(qhla, 48, 16);
1607
PRECEQ_PW(qhra, 32, 0);
1608

    
1609
#undef PRECEQ_PW
1610

    
1611
#endif
1612

    
1613
#define PRECEQU_PH(name, a, b) \
1614
target_ulong helper_precequ_ph_##name(target_ulong rt) \
1615
{                                                        \
1616
    uint16_t tempB, tempA;                               \
1617
                                                         \
1618
    tempB = (rt >> a) & MIPSDSP_Q0;                      \
1619
    tempA = (rt >> b) & MIPSDSP_Q0;                      \
1620
                                                         \
1621
    tempB = tempB << 7;                                  \
1622
    tempA = tempA << 7;                                  \
1623
                                                         \
1624
    return MIPSDSP_RETURN32_16(tempB, tempA);            \
1625
}
1626

    
1627
PRECEQU_PH(qbl, 24, 16);
1628
PRECEQU_PH(qbr, 8, 0);
1629
PRECEQU_PH(qbla, 24, 8);
1630
PRECEQU_PH(qbra, 16, 0);
1631

    
1632
#undef PRECEQU_PH
1633

    
1634
#if defined(TARGET_MIPS64)
1635
#define PRECEQU_QH(name, a, b, c, d) \
1636
target_ulong helper_precequ_qh_##name(target_ulong rt)       \
1637
{                                                            \
1638
    uint16_t tempD, tempC, tempB, tempA;                     \
1639
                                                             \
1640
    tempD = (rt >> a) & MIPSDSP_Q0;                          \
1641
    tempC = (rt >> b) & MIPSDSP_Q0;                          \
1642
    tempB = (rt >> c) & MIPSDSP_Q0;                          \
1643
    tempA = (rt >> d) & MIPSDSP_Q0;                          \
1644
                                                             \
1645
    tempD = tempD << 7;                                      \
1646
    tempC = tempC << 7;                                      \
1647
    tempB = tempB << 7;                                      \
1648
    tempA = tempA << 7;                                      \
1649
                                                             \
1650
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1651
}
1652

    
1653
PRECEQU_QH(obl, 56, 48, 40, 32);
1654
PRECEQU_QH(obr, 24, 16, 8, 0);
1655
PRECEQU_QH(obla, 56, 40, 24, 8);
1656
PRECEQU_QH(obra, 48, 32, 16, 0);
1657

    
1658
#undef PRECEQU_QH
1659

    
1660
#endif
1661

    
1662
#define PRECEU_PH(name, a, b) \
1663
target_ulong helper_preceu_ph_##name(target_ulong rt) \
1664
{                                                     \
1665
    uint16_t tempB, tempA;                            \
1666
                                                      \
1667
    tempB = (rt >> a) & MIPSDSP_Q0;                   \
1668
    tempA = (rt >> b) & MIPSDSP_Q0;                   \
1669
                                                      \
1670
    return MIPSDSP_RETURN32_16(tempB, tempA);         \
1671
}
1672

    
1673
PRECEU_PH(qbl, 24, 16);
1674
PRECEU_PH(qbr, 8, 0);
1675
PRECEU_PH(qbla, 24, 8);
1676
PRECEU_PH(qbra, 16, 0);
1677

    
1678
#undef PRECEU_PH
1679

    
1680
#if defined(TARGET_MIPS64)
1681
#define PRECEU_QH(name, a, b, c, d) \
1682
target_ulong helper_preceu_qh_##name(target_ulong rt)        \
1683
{                                                            \
1684
    uint16_t tempD, tempC, tempB, tempA;                     \
1685
                                                             \
1686
    tempD = (rt >> a) & MIPSDSP_Q0;                          \
1687
    tempC = (rt >> b) & MIPSDSP_Q0;                          \
1688
    tempB = (rt >> c) & MIPSDSP_Q0;                          \
1689
    tempA = (rt >> d) & MIPSDSP_Q0;                          \
1690
                                                             \
1691
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1692
}
1693

    
1694
PRECEU_QH(obl, 56, 48, 40, 32);
1695
PRECEU_QH(obr, 24, 16, 8, 0);
1696
PRECEU_QH(obla, 56, 40, 24, 8);
1697
PRECEU_QH(obra, 48, 32, 16, 0);
1698

    
1699
#undef PRECEU_QH
1700

    
1701
#endif
1702

    
1703
/** DSP GPR-Based Shift Sub-class insns **/
1704
#define SHIFT_QB(name, func) \
1705
target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \
1706
{                                                                    \
1707
    uint8_t rt3, rt2, rt1, rt0;                                      \
1708
                                                                     \
1709
    sa = sa & 0x07;                                                  \
1710
                                                                     \
1711
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
1712
                                                                     \
1713
    rt3 = mipsdsp_##func(rt3, sa);                                   \
1714
    rt2 = mipsdsp_##func(rt2, sa);                                   \
1715
    rt1 = mipsdsp_##func(rt1, sa);                                   \
1716
    rt0 = mipsdsp_##func(rt0, sa);                                   \
1717
                                                                     \
1718
    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
1719
}
1720

    
1721
#define SHIFT_QB_ENV(name, func) \
1722
target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\
1723
                                CPUMIPSState *env) \
1724
{                                                                    \
1725
    uint8_t rt3, rt2, rt1, rt0;                                      \
1726
                                                                     \
1727
    sa = sa & 0x07;                                                  \
1728
                                                                     \
1729
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
1730
                                                                     \
1731
    rt3 = mipsdsp_##func(rt3, sa, env);                              \
1732
    rt2 = mipsdsp_##func(rt2, sa, env);                              \
1733
    rt1 = mipsdsp_##func(rt1, sa, env);                              \
1734
    rt0 = mipsdsp_##func(rt0, sa, env);                              \
1735
                                                                     \
1736
    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
1737
}
1738

    
1739
SHIFT_QB_ENV(shll, lshift8);
1740
SHIFT_QB(shrl, rshift_u8);
1741

    
1742
SHIFT_QB(shra, rashift8);
1743
SHIFT_QB(shra_r, rnd8_rashift);
1744

    
1745
#undef SHIFT_QB
1746
#undef SHIFT_QB_ENV
1747

    
1748
#if defined(TARGET_MIPS64)
1749
#define SHIFT_OB(name, func) \
1750
target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
1751
{                                                                        \
1752
    int i;                                                               \
1753
    uint8_t rt_t[8];                                                     \
1754
    uint64_t temp;                                                       \
1755
                                                                         \
1756
    sa = sa & 0x07;                                                      \
1757
    temp = 0;                                                            \
1758
                                                                         \
1759
    for (i = 0; i < 8; i++) {                                            \
1760
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
1761
        rt_t[i] = mipsdsp_##func(rt_t[i], sa);                           \
1762
        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
1763
    }                                                                    \
1764
                                                                         \
1765
    return temp;                                                         \
1766
}
1767

    
1768
#define SHIFT_OB_ENV(name, func) \
1769
target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
1770
                                CPUMIPSState *env)                       \
1771
{                                                                        \
1772
    int i;                                                               \
1773
    uint8_t rt_t[8];                                                     \
1774
    uint64_t temp;                                                       \
1775
                                                                         \
1776
    sa = sa & 0x07;                                                      \
1777
    temp = 0;                                                            \
1778
                                                                         \
1779
    for (i = 0; i < 8; i++) {                                            \
1780
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
1781
        rt_t[i] = mipsdsp_##func(rt_t[i], sa, env);                      \
1782
        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
1783
    }                                                                    \
1784
                                                                         \
1785
    return temp;                                                         \
1786
}
1787

    
1788
SHIFT_OB_ENV(shll, lshift8);
1789
SHIFT_OB(shrl, rshift_u8);
1790

    
1791
SHIFT_OB(shra, rashift8);
1792
SHIFT_OB(shra_r, rnd8_rashift);
1793

    
1794
#undef SHIFT_OB
1795
#undef SHIFT_OB_ENV
1796

    
1797
#endif
1798

    
1799
#define SHIFT_PH(name, func) \
1800
target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \
1801
                                CPUMIPSState *env)                \
1802
{                                                                 \
1803
    uint16_t rth, rtl;                                            \
1804
                                                                  \
1805
    sa = sa & 0x0F;                                               \
1806
                                                                  \
1807
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
1808
                                                                  \
1809
    rth = mipsdsp_##func(rth, sa, env);                           \
1810
    rtl = mipsdsp_##func(rtl, sa, env);                           \
1811
                                                                  \
1812
    return MIPSDSP_RETURN32_16(rth, rtl);                         \
1813
}
1814

    
1815
SHIFT_PH(shll, lshift16);
1816
SHIFT_PH(shll_s, sat16_lshift);
1817

    
1818
#undef SHIFT_PH
1819

    
1820
#if defined(TARGET_MIPS64)
1821
#define SHIFT_QH(name, func) \
1822
target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \
1823
{                                                                 \
1824
    uint16_t rt3, rt2, rt1, rt0;                                  \
1825
                                                                  \
1826
    sa = sa & 0x0F;                                               \
1827
                                                                  \
1828
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
1829
                                                                  \
1830
    rt3 = mipsdsp_##func(rt3, sa);                                \
1831
    rt2 = mipsdsp_##func(rt2, sa);                                \
1832
    rt1 = mipsdsp_##func(rt1, sa);                                \
1833
    rt0 = mipsdsp_##func(rt0, sa);                                \
1834
                                                                  \
1835
    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
1836
}
1837

    
1838
#define SHIFT_QH_ENV(name, func) \
1839
target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \
1840
                                CPUMIPSState *env)                \
1841
{                                                                 \
1842
    uint16_t rt3, rt2, rt1, rt0;                                  \
1843
                                                                  \
1844
    sa = sa & 0x0F;                                               \
1845
                                                                  \
1846
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
1847
                                                                  \
1848
    rt3 = mipsdsp_##func(rt3, sa, env);                           \
1849
    rt2 = mipsdsp_##func(rt2, sa, env);                           \
1850
    rt1 = mipsdsp_##func(rt1, sa, env);                           \
1851
    rt0 = mipsdsp_##func(rt0, sa, env);                           \
1852
                                                                  \
1853
    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
1854
}
1855

    
1856
SHIFT_QH_ENV(shll, lshift16);
1857
SHIFT_QH_ENV(shll_s, sat16_lshift);
1858

    
1859
SHIFT_QH(shrl, rshift_u16);
1860
SHIFT_QH(shra, rashift16);
1861
SHIFT_QH(shra_r, rnd16_rashift);
1862

    
1863
#undef SHIFT_QH
1864
#undef SHIFT_QH_ENV
1865

    
1866
#endif
1867

    
1868
#define SHIFT_W(name, func) \
1869
target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
1870
{                                                                       \
1871
    uint32_t temp;                                                      \
1872
                                                                        \
1873
    sa = sa & 0x1F;                                                     \
1874
    temp = mipsdsp_##func(rt, sa);                                      \
1875
                                                                        \
1876
    return (target_long)(int32_t)temp;                                  \
1877
}
1878

    
1879
#define SHIFT_W_ENV(name, func) \
1880
target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \
1881
                               CPUMIPSState *env) \
1882
{                                                                       \
1883
    uint32_t temp;                                                      \
1884
                                                                        \
1885
    sa = sa & 0x1F;                                                     \
1886
    temp = mipsdsp_##func(rt, sa, env);                                 \
1887
                                                                        \
1888
    return (target_long)(int32_t)temp;                                  \
1889
}
1890

    
1891
SHIFT_W_ENV(shll_s, sat32_lshift);
1892
SHIFT_W(shra_r, rnd32_rashift);
1893

    
1894
#undef SHIFT_W
1895
#undef SHIFT_W_ENV
1896

    
1897
#if defined(TARGET_MIPS64)
1898
#define SHIFT_PW(name, func) \
1899
target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \
1900
{                                                                 \
1901
    uint32_t rt1, rt0;                                            \
1902
                                                                  \
1903
    sa = sa & 0x1F;                                               \
1904
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
1905
                                                                  \
1906
    rt1 = mipsdsp_##func(rt1, sa);                                \
1907
    rt0 = mipsdsp_##func(rt0, sa);                                \
1908
                                                                  \
1909
    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
1910
}
1911

    
1912
#define SHIFT_PW_ENV(name, func) \
1913
target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \
1914
                                CPUMIPSState *env)                \
1915
{                                                                 \
1916
    uint32_t rt1, rt0;                                            \
1917
                                                                  \
1918
    sa = sa & 0x1F;                                               \
1919
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
1920
                                                                  \
1921
    rt1 = mipsdsp_##func(rt1, sa, env);                           \
1922
    rt0 = mipsdsp_##func(rt0, sa, env);                           \
1923
                                                                  \
1924
    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
1925
}
1926

    
1927
SHIFT_PW_ENV(shll, lshift32);
1928
SHIFT_PW_ENV(shll_s, sat32_lshift);
1929

    
1930
SHIFT_PW(shra, rashift32);
1931
SHIFT_PW(shra_r, rnd32_rashift);
1932

    
1933
#undef SHIFT_PW
1934
#undef SHIFT_PW_ENV
1935

    
1936
#endif
1937

    
1938
#define SHIFT_PH(name, func) \
1939
target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
1940
{                                                                    \
1941
    uint16_t rth, rtl;                                               \
1942
                                                                     \
1943
    sa = sa & 0x0F;                                                  \
1944
                                                                     \
1945
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                \
1946
                                                                     \
1947
    rth = mipsdsp_##func(rth, sa);                                   \
1948
    rtl = mipsdsp_##func(rtl, sa);                                   \
1949
                                                                     \
1950
    return MIPSDSP_RETURN32_16(rth, rtl);                            \
1951
}
1952

    
1953
SHIFT_PH(shrl, rshift_u16);
1954
SHIFT_PH(shra, rashift16);
1955
SHIFT_PH(shra_r, rnd16_rashift);
1956

    
1957
#undef SHIFT_PH
1958

    
1959
/** DSP Multiply Sub-class insns **/
1960
/* Return value made up by two 16bits value.
1961
 * FIXME give the macro a better name.
1962
 */
1963
#define MUL_RETURN32_16_PH(name, func, \
1964
                           rsmov1, rsmov2, rsfilter, \
1965
                           rtmov1, rtmov2, rtfilter) \
1966
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
1967
                           CPUMIPSState *env)                \
1968
{                                                            \
1969
    uint16_t rsB, rsA, rtB, rtA;                             \
1970
                                                             \
1971
    rsB = (rs >> rsmov1) & rsfilter;                         \
1972
    rsA = (rs >> rsmov2) & rsfilter;                         \
1973
    rtB = (rt >> rtmov1) & rtfilter;                         \
1974
    rtA = (rt >> rtmov2) & rtfilter;                         \
1975
                                                             \
1976
    rsB = mipsdsp_##func(rsB, rtB, env);                     \
1977
    rsA = mipsdsp_##func(rsA, rtA, env);                     \
1978
                                                             \
1979
    return MIPSDSP_RETURN32_16(rsB, rsA);                    \
1980
}
1981

    
1982
MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \
1983
                      24, 16, MIPSDSP_Q0, \
1984
                      16, 0, MIPSDSP_LO);
1985
MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \
1986
                      8, 0, MIPSDSP_Q0, \
1987
                      16, 0, MIPSDSP_LO);
1988
MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \
1989
                      16, 0, MIPSDSP_LO, \
1990
                      16, 0, MIPSDSP_LO);
1991
MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \
1992
                      16, 0, MIPSDSP_LO, \
1993
                      16, 0, MIPSDSP_LO);
1994
MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \
1995
                      16, 0, MIPSDSP_LO, \
1996
                      16, 0, MIPSDSP_LO);
1997
MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \
1998
                      16, 0, MIPSDSP_LO, \
1999
                      16, 0, MIPSDSP_LO);
2000

    
2001
#undef MUL_RETURN32_16_PH
2002

    
2003
#define MUL_RETURN32_32_ph(name, func, movbits) \
2004
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2005
                                  CPUMIPSState *env)         \
2006
{                                                            \
2007
    int16_t rsh, rth;                                        \
2008
    int32_t temp;                                            \
2009
                                                             \
2010
    rsh = (rs >> movbits) & MIPSDSP_LO;                      \
2011
    rth = (rt >> movbits) & MIPSDSP_LO;                      \
2012
    temp = mipsdsp_##func(rsh, rth, env);                    \
2013
                                                             \
2014
    return (target_long)(int32_t)temp;                       \
2015
}
2016

    
2017
MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16);
2018
MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0);
2019

    
2020
#undef MUL_RETURN32_32_ph
2021

    
2022
#define MUL_VOID_PH(name, use_ac_env) \
2023
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
2024
                          CPUMIPSState *env)                             \
2025
{                                                                        \
2026
    int16_t rsh, rsl, rth, rtl;                                          \
2027
    int32_t tempB, tempA;                                                \
2028
    int64_t acc, dotp;                                                   \
2029
                                                                         \
2030
    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
2031
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
2032
                                                                         \
2033
    if (use_ac_env == 1) {                                               \
2034
        tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                  \
2035
        tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env);                  \
2036
    } else {                                                             \
2037
        tempB = mipsdsp_mul_u16_u16(rsh, rth);                           \
2038
        tempA = mipsdsp_mul_u16_u16(rsl, rtl);                           \
2039
    }                                                                    \
2040
                                                                         \
2041
    dotp = (int64_t)tempB - (int64_t)tempA;                              \
2042
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                      \
2043
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);               \
2044
    dotp = dotp + acc;                                                   \
2045
    env->active_tc.HI[ac] = (target_long)(int32_t)                       \
2046
                            ((dotp & MIPSDSP_LHI) >> 32);                \
2047
    env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO);  \
2048
}
2049

    
2050
MUL_VOID_PH(mulsaq_s_w_ph, 1);
2051
MUL_VOID_PH(mulsa_w_ph, 0);
2052

    
2053
#undef MUL_VOID_PH
2054

    
2055
#if defined(TARGET_MIPS64)
2056
#define MUL_RETURN64_16_QH(name, func, \
2057
                           rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \
2058
                           rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \
2059
target_ulong helper_##name(target_ulong rs, target_ulong rt,         \
2060
                           CPUMIPSState *env)                        \
2061
{                                                                    \
2062
    uint16_t rs3, rs2, rs1, rs0;                                     \
2063
    uint16_t rt3, rt2, rt1, rt0;                                     \
2064
    uint16_t tempD, tempC, tempB, tempA;                             \
2065
                                                                     \
2066
    rs3 = (rs >> rsmov1) & rsfilter;                                 \
2067
    rs2 = (rs >> rsmov2) & rsfilter;                                 \
2068
    rs1 = (rs >> rsmov3) & rsfilter;                                 \
2069
    rs0 = (rs >> rsmov4) & rsfilter;                                 \
2070
    rt3 = (rt >> rtmov1) & rtfilter;                                 \
2071
    rt2 = (rt >> rtmov2) & rtfilter;                                 \
2072
    rt1 = (rt >> rtmov3) & rtfilter;                                 \
2073
    rt0 = (rt >> rtmov4) & rtfilter;                                 \
2074
                                                                     \
2075
    tempD = mipsdsp_##func(rs3, rt3, env);                           \
2076
    tempC = mipsdsp_##func(rs2, rt2, env);                           \
2077
    tempB = mipsdsp_##func(rs1, rt1, env);                           \
2078
    tempA = mipsdsp_##func(rs0, rt0, env);                           \
2079
                                                                     \
2080
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);          \
2081
}
2082

    
2083
MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \
2084
                   56, 48, 40, 32, MIPSDSP_Q0, \
2085
                   48, 32, 16, 0, MIPSDSP_LO);
2086
MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \
2087
                   24, 16, 8, 0, MIPSDSP_Q0, \
2088
                   48, 32, 16, 0, MIPSDSP_LO);
2089
MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \
2090
                   48, 32, 16, 0, MIPSDSP_LO, \
2091
                   48, 32, 16, 0, MIPSDSP_LO);
2092

    
2093
#undef MUL_RETURN64_16_QH
2094

    
2095
#define MUL_RETURN64_32_QH(name, \
2096
                           rsmov1, rsmov2, \
2097
                           rtmov1, rtmov2) \
2098
target_ulong helper_##name(target_ulong rs, target_ulong rt, \
2099
                           CPUMIPSState *env)                \
2100
{                                                            \
2101
    uint16_t rsB, rsA;                                       \
2102
    uint16_t rtB, rtA;                                       \
2103
    uint32_t tempB, tempA;                                   \
2104
                                                             \
2105
    rsB = (rs >> rsmov1) & MIPSDSP_LO;                       \
2106
    rsA = (rs >> rsmov2) & MIPSDSP_LO;                       \
2107
    rtB = (rt >> rtmov1) & MIPSDSP_LO;                       \
2108
    rtA = (rt >> rtmov2) & MIPSDSP_LO;                       \
2109
                                                             \
2110
    tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env);           \
2111
    tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env);           \
2112
                                                             \
2113
    return ((uint64_t)tempB << 32) | (uint64_t)tempA;        \
2114
}
2115

    
2116
MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32);
2117
MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0);
2118

    
2119
#undef MUL_RETURN64_32_QH
2120

    
2121
void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac,
2122
                          CPUMIPSState *env)
2123
{
2124
    int16_t rs3, rs2, rs1, rs0;
2125
    int16_t rt3, rt2, rt1, rt0;
2126
    int32_t tempD, tempC, tempB, tempA;
2127
    int64_t acc[2];
2128
    int64_t temp[2];
2129
    int64_t temp_sum;
2130

    
2131
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
2132
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
2133

    
2134
    tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);
2135
    tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);
2136
    tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);
2137
    tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);
2138

    
2139
    temp[0] = ((int32_t)tempD - (int32_t)tempC) +
2140
              ((int32_t)tempB - (int32_t)tempA);
2141
    temp[0] = (int64_t)(temp[0] << 30) >> 30;
2142
    if (((temp[0] >> 33) & 0x01) == 0) {
2143
        temp[1] = 0x00;
2144
    } else {
2145
        temp[1] = ~0ull;
2146
    }
2147

    
2148
    acc[0] = env->active_tc.LO[ac];
2149
    acc[1] = env->active_tc.HI[ac];
2150

    
2151
    temp_sum = acc[0] + temp[0];
2152
    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
2153
       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
2154
        acc[1] += 1;
2155
    }
2156
    acc[0] = temp_sum;
2157
    acc[1] += temp[1];
2158

    
2159
    env->active_tc.HI[ac] = acc[1];
2160
    env->active_tc.LO[ac] = acc[0];
2161
}
2162
#endif
2163

    
2164
#define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
2165
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
2166
                   CPUMIPSState *env)                                    \
2167
{                                                                        \
2168
    uint8_t rs3, rs2;                                                    \
2169
    uint8_t rt3, rt2;                                                    \
2170
    uint16_t tempB, tempA;                                               \
2171
    uint64_t tempC, dotp;                                                \
2172
                                                                         \
2173
    rs3 = (rs >> rsmov1) & MIPSDSP_Q0;                                   \
2174
    rs2 = (rs >> rsmov2) & MIPSDSP_Q0;                                   \
2175
    rt3 = (rt >> rtmov1) & MIPSDSP_Q0;                                   \
2176
    rt2 = (rt >> rtmov2) & MIPSDSP_Q0;                                   \
2177
    tempB = mipsdsp_##func(rs3, rt3);                                    \
2178
    tempA = mipsdsp_##func(rs2, rt2);                                    \
2179
    dotp = (int64_t)tempB + (int64_t)tempA;                              \
2180
    if (is_add) {                                                        \
2181
        tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |               \
2182
                 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO))        \
2183
            + dotp;                                                      \
2184
    } else {                                                             \
2185
        tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |               \
2186
                 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO))        \
2187
            - dotp;                                                      \
2188
    }                                                                    \
2189
                                                                         \
2190
    env->active_tc.HI[ac] = (target_long)(int32_t)                       \
2191
                            ((tempC & MIPSDSP_LHI) >> 32);               \
2192
    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \
2193
}
2194

    
2195
DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16);
2196
DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0);
2197
DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16);
2198
DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0);
2199

    
2200
#undef DP_QB
2201

    
2202
#if defined(TARGET_MIPS64)
2203
#define DP_OB(name, add_sub, \
2204
              rsmov1, rsmov2, rsmov3, rsmov4, \
2205
              rtmov1, rtmov2, rtmov3, rtmov4) \
2206
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,       \
2207
                       CPUMIPSState *env)                               \
2208
{                                                                       \
2209
    uint8_t rsD, rsC, rsB, rsA;                                         \
2210
    uint8_t rtD, rtC, rtB, rtA;                                         \
2211
    uint16_t tempD, tempC, tempB, tempA;                                \
2212
    uint64_t temp[2];                                                   \
2213
    uint64_t acc[2];                                                    \
2214
    uint64_t temp_sum;                                                  \
2215
                                                                        \
2216
    temp[0] = 0;                                                        \
2217
    temp[1] = 0;                                                        \
2218
                                                                        \
2219
    rsD = (rs >> rsmov1) & MIPSDSP_Q0;                                  \
2220
    rsC = (rs >> rsmov2) & MIPSDSP_Q0;                                  \
2221
    rsB = (rs >> rsmov3) & MIPSDSP_Q0;                                  \
2222
    rsA = (rs >> rsmov4) & MIPSDSP_Q0;                                  \
2223
    rtD = (rt >> rtmov1) & MIPSDSP_Q0;                                  \
2224
    rtC = (rt >> rtmov2) & MIPSDSP_Q0;                                  \
2225
    rtB = (rt >> rtmov3) & MIPSDSP_Q0;                                  \
2226
    rtA = (rt >> rtmov4) & MIPSDSP_Q0;                                  \
2227
                                                                        \
2228
    tempD = mipsdsp_mul_u8_u8(rsD, rtD);                                \
2229
    tempC = mipsdsp_mul_u8_u8(rsC, rtC);                                \
2230
    tempB = mipsdsp_mul_u8_u8(rsB, rtB);                                \
2231
    tempA = mipsdsp_mul_u8_u8(rsA, rtA);                                \
2232
                                                                        \
2233
    temp[0] = (uint64_t)tempD + (uint64_t)tempC +                       \
2234
      (uint64_t)tempB + (uint64_t)tempA;                                \
2235
                                                                        \
2236
    acc[0] = env->active_tc.LO[ac];                                     \
2237
    acc[1] = env->active_tc.HI[ac];                                     \
2238
                                                                        \
2239
    if (add_sub) {                                                      \
2240
        temp_sum = acc[0] + temp[0];                                    \
2241
        if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&                  \
2242
            ((uint64_t)temp_sum < (uint64_t)temp[0])) {                 \
2243
            acc[1] += 1;                                                \
2244
        }                                                               \
2245
        temp[0] = temp_sum;                                             \
2246
        temp[1] = acc[1] + temp[1];                                     \
2247
    } else {                                                            \
2248
        temp_sum = acc[0] - temp[0];                                    \
2249
        if ((uint64_t)temp_sum > (uint64_t)acc[0]) {                    \
2250
            acc[1] -= 1;                                                \
2251
        }                                                               \
2252
        temp[0] = temp_sum;                                             \
2253
        temp[1] = acc[1] - temp[1];                                     \
2254
    }                                                                   \
2255
                                                                        \
2256
    env->active_tc.HI[ac] = temp[1];                                    \
2257
    env->active_tc.LO[ac] = temp[0];                                    \
2258
}
2259

    
2260
DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32);
2261
DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0);
2262
DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32);
2263
DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0);
2264

    
2265
#undef DP_OB
2266
#endif
2267

    
2268
#define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2)             \
2269
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,              \
2270
                   CPUMIPSState *env)                                          \
2271
{                                                                              \
2272
    int16_t rsB, rsA, rtB, rtA;                                                \
2273
    int32_t  tempA, tempB;                                                     \
2274
    int64_t  acc;                                                              \
2275
                                                                               \
2276
    rsB = (rs >> rsmov1) & MIPSDSP_LO;                                         \
2277
    rsA = (rs >> rsmov2) & MIPSDSP_LO;                                         \
2278
    rtB = (rt >> rtmov1) & MIPSDSP_LO;                                         \
2279
    rtA = (rt >> rtmov2) & MIPSDSP_LO;                                         \
2280
                                                                               \
2281
    tempB = (int32_t)rsB * (int32_t)rtB;                                       \
2282
    tempA = (int32_t)rsA * (int32_t)rtA;                                       \
2283
                                                                               \
2284
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                            \
2285
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);                     \
2286
                                                                               \
2287
    if (is_add) {                                                              \
2288
        acc = acc + ((int64_t)tempB + (int64_t)tempA);                         \
2289
    } else {                                                                   \
2290
        acc = acc - ((int64_t)tempB + (int64_t)tempA);                         \
2291
    }                                                                          \
2292
                                                                               \
2293
    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \
2294
    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);         \
2295
}
2296

    
2297
DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0);
2298
DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16);
2299
DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0);
2300
DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16);
2301
#undef DP_NOFUNC_PH
2302

    
2303
#define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
2304
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,   \
2305
                   CPUMIPSState *env)                      \
2306
{                                                          \
2307
    int16_t rsB, rsA, rtB, rtA;                            \
2308
    int32_t tempB, tempA;                                  \
2309
    int64_t acc, dotp;                                     \
2310
                                                           \
2311
    rsB = (rs >> rsmov1) & MIPSDSP_LO;                     \
2312
    rsA = (rs >> rsmov2) & MIPSDSP_LO;                     \
2313
    rtB = (rt >> rtmov1) & MIPSDSP_LO;                     \
2314
    rtA = (rt >> rtmov2) & MIPSDSP_LO;                     \
2315
                                                           \
2316
    tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env);        \
2317
    tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env);        \
2318
                                                           \
2319
    dotp = (int64_t)tempB + (int64_t)tempA;                \
2320
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |        \
2321
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
2322
                                                           \
2323
    if (is_add) {                                          \
2324
        acc = acc + dotp;                                  \
2325
    } else {                                               \
2326
        acc = acc - dotp;                                  \
2327
    }                                                      \
2328
                                                           \
2329
    env->active_tc.HI[ac] = (target_long)(int32_t)         \
2330
        ((acc & MIPSDSP_LHI) >> 32);                       \
2331
    env->active_tc.LO[ac] = (target_long)(int32_t)         \
2332
        (acc & MIPSDSP_LLO);                               \
2333
}
2334

    
2335
DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0);
2336
DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16);
2337
DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0);
2338
DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16);
2339

    
2340
#undef DP_HASFUNC_PH
2341

    
2342
#define DP_128OPERATION_PH(name, is_add) \
2343
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2344
                          CPUMIPSState *env)                             \
2345
{                                                                        \
2346
    int16_t rsh, rsl, rth, rtl;                                          \
2347
    int32_t tempB, tempA, tempC62_31, tempC63;                           \
2348
    int64_t acc, dotp, tempC;                                            \
2349
                                                                         \
2350
    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
2351
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
2352
                                                                         \
2353
    tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env);                      \
2354
    tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env);                      \
2355
                                                                         \
2356
    dotp = (int64_t)tempB + (int64_t)tempA;                              \
2357
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                      \
2358
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);               \
2359
    if (is_add) {                                                        \
2360
        tempC = acc + dotp;                                              \
2361
    } else {                                                             \
2362
        tempC = acc - dotp;                                              \
2363
    }                                                                    \
2364
    tempC63 = (tempC >> 63) & 0x01;                                      \
2365
    tempC62_31 = (tempC >> 31) & 0xFFFFFFFF;                             \
2366
                                                                         \
2367
    if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) {                  \
2368
        tempC = 0x7FFFFFFF;                                              \
2369
        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
2370
    }                                                                    \
2371
                                                                         \
2372
    if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) {                  \
2373
        tempC = (int64_t)(int32_t)0x80000000;                            \
2374
        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
2375
    }                                                                    \
2376
                                                                         \
2377
    env->active_tc.HI[ac] = (target_long)(int32_t)                       \
2378
        ((tempC & MIPSDSP_LHI) >> 32);                                   \
2379
    env->active_tc.LO[ac] = (target_long)(int32_t)                       \
2380
        (tempC & MIPSDSP_LLO);                                           \
2381
}
2382

    
2383
DP_128OPERATION_PH(dpaqx_sa_w_ph, 1);
2384
DP_128OPERATION_PH(dpsqx_sa_w_ph, 0);
2385

    
2386
#undef DP_128OPERATION_HP
2387

    
2388
#if defined(TARGET_MIPS64)
2389
#define DP_QH(name, is_add, use_ac_env) \
2390
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
2391
                   CPUMIPSState *env)                                \
2392
{                                                                    \
2393
    int32_t rs3, rs2, rs1, rs0;                                      \
2394
    int32_t rt3, rt2, rt1, rt0;                                      \
2395
    int32_t tempD, tempC, tempB, tempA;                              \
2396
    int64_t acc[2];                                                  \
2397
    int64_t temp[2];                                                 \
2398
    int64_t temp_sum;                                                \
2399
                                                                     \
2400
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                      \
2401
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                      \
2402
                                                                     \
2403
    if (use_ac_env) {                                                \
2404
        tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);              \
2405
        tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);              \
2406
        tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);              \
2407
        tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);              \
2408
    } else {                                                         \
2409
        tempD = mipsdsp_mul_u16_u16(rs3, rt3);                       \
2410
        tempC = mipsdsp_mul_u16_u16(rs2, rt2);                       \
2411
        tempB = mipsdsp_mul_u16_u16(rs1, rt1);                       \
2412
        tempA = mipsdsp_mul_u16_u16(rs0, rt0);                       \
2413
    }                                                                \
2414
                                                                     \
2415
    temp[0] = (int64_t)tempD + (int64_t)tempC +                      \
2416
              (int64_t)tempB + (int64_t)tempA;                       \
2417
                                                                     \
2418
    if (temp[0] >= 0) {                                              \
2419
        temp[1] = 0;                                                 \
2420
    } else {                                                         \
2421
        temp[1] = ~0ull;                                             \
2422
    }                                                                \
2423
                                                                     \
2424
    acc[1] = env->active_tc.HI[ac];                                  \
2425
    acc[0] = env->active_tc.LO[ac];                                  \
2426
                                                                     \
2427
    if (is_add) {                                                    \
2428
        temp_sum = acc[0] + temp[0];                                 \
2429
        if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&               \
2430
            ((uint64_t)temp_sum < (uint64_t)temp[0])) {              \
2431
            acc[1] = acc[1] + 1;                                     \
2432
        }                                                            \
2433
        temp[0] = temp_sum;                                          \
2434
        temp[1] = acc[1] + temp[1];                                  \
2435
    } else {                                                         \
2436
        temp_sum = acc[0] - temp[0];                                 \
2437
        if ((uint64_t)temp_sum > (uint64_t)acc[0]) {                 \
2438
            acc[1] = acc[1] - 1;                                     \
2439
        }                                                            \
2440
        temp[0] = temp_sum;                                          \
2441
        temp[1] = acc[1] - temp[1];                                  \
2442
    }                                                                \
2443
                                                                     \
2444
    env->active_tc.HI[ac] = temp[1];                                 \
2445
    env->active_tc.LO[ac] = temp[0];                                 \
2446
}
2447

    
2448
DP_QH(dpa_w_qh, 1, 0);
2449
DP_QH(dpaq_s_w_qh, 1, 1);
2450
DP_QH(dps_w_qh, 0, 0);
2451
DP_QH(dpsq_s_w_qh, 0, 1);
2452

    
2453
#undef DP_QH
2454

    
2455
#endif
2456

    
2457
#define DP_L_W(name, is_add) \
2458
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,      \
2459
                   CPUMIPSState *env)                                  \
2460
{                                                                      \
2461
    int32_t temp63;                                                    \
2462
    int64_t dotp, acc;                                                 \
2463
    uint64_t temp;                                                     \
2464
    bool overflow;                                                     \
2465
                                                                       \
2466
    dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env);                       \
2467
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                    \
2468
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);             \
2469
    if (is_add) {                                                      \
2470
        temp = acc + dotp;                                             \
2471
        overflow = MIPSDSP_OVERFLOW_ADD((uint64_t)acc, (uint64_t)dotp, \
2472
                                        temp, (0x01ull << 63));        \
2473
    } else {                                                           \
2474
        temp = acc - dotp;                                             \
2475
        overflow = MIPSDSP_OVERFLOW_SUB((uint64_t)acc, (uint64_t)dotp, \
2476
                                        temp, (0x01ull << 63));        \
2477
    }                                                                  \
2478
                                                                       \
2479
    if (overflow) {                                                    \
2480
        temp63 = (temp >> 63) & 0x01;                                  \
2481
        if (temp63 == 1) {                                             \
2482
            temp = (0x01ull << 63) - 1;                                \
2483
        } else {                                                       \
2484
            temp = 0x01ull << 63;                                      \
2485
        }                                                              \
2486
                                                                       \
2487
        set_DSPControl_overflow_flag(1, 16 + ac, env);                 \
2488
    }                                                                  \
2489
                                                                       \
2490
    env->active_tc.HI[ac] = (target_long)(int32_t)                     \
2491
        ((temp & MIPSDSP_LHI) >> 32);                                  \
2492
    env->active_tc.LO[ac] = (target_long)(int32_t)                     \
2493
        (temp & MIPSDSP_LLO);                                          \
2494
}
2495

    
2496
DP_L_W(dpaq_sa_l_w, 1);
2497
DP_L_W(dpsq_sa_l_w, 0);
2498

    
2499
#undef DP_L_W
2500

    
2501
#if defined(TARGET_MIPS64)
2502
#define DP_L_PW(name, func) \
2503
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2504
                   CPUMIPSState *env)                             \
2505
{                                                                 \
2506
    int32_t rs1, rs0;                                             \
2507
    int32_t rt1, rt0;                                             \
2508
    int64_t tempB[2], tempA[2];                                   \
2509
    int64_t temp[2];                                              \
2510
    int64_t acc[2];                                               \
2511
    int64_t temp_sum;                                             \
2512
                                                                  \
2513
    temp[0] = 0;                                                  \
2514
    temp[1] = 0;                                                  \
2515
                                                                  \
2516
    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
2517
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
2518
                                                                  \
2519
    tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);            \
2520
    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);            \
2521
                                                                  \
2522
    if (tempB[0] >= 0) {                                          \
2523
        tempB[1] = 0x00;                                          \
2524
    } else {                                                      \
2525
        tempB[1] = ~0ull;                                         \
2526
    }                                                             \
2527
                                                                  \
2528
    if (tempA[0] >= 0) {                                          \
2529
        tempA[1] = 0x00;                                          \
2530
    } else {                                                      \
2531
        tempA[1] = ~0ull;                                         \
2532
    }                                                             \
2533
                                                                  \
2534
    temp_sum = tempB[0] + tempA[0];                               \
2535
    if (((uint64_t)temp_sum < (uint64_t)tempB[0]) &&              \
2536
        ((uint64_t)temp_sum < (uint64_t)tempA[0])) {              \
2537
        temp[1] += 1;                                             \
2538
    }                                                             \
2539
    temp[0] = temp_sum;                                           \
2540
    temp[1] += tempB[1] + tempA[1];                               \
2541
                                                                  \
2542
    mipsdsp_##func(acc, ac, temp, env);                           \
2543
                                                                  \
2544
    env->active_tc.HI[ac] = acc[1];                               \
2545
    env->active_tc.LO[ac] = acc[0];                               \
2546
}
2547

    
2548
DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63);
2549
DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63);
2550

    
2551
#undef DP_L_PW
2552

    
2553
void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac,
2554
                          CPUMIPSState *env)
2555
{
2556
    int32_t rs1, rs0;
2557
    int32_t rt1, rt0;
2558
    int64_t tempB[2], tempA[2];
2559
    int64_t temp[2];
2560
    int64_t acc[2];
2561
    int64_t temp_sum;
2562

    
2563
    rs1 = (rs >> 32) & MIPSDSP_LLO;
2564
    rs0 = rs & MIPSDSP_LLO;
2565
    rt1 = (rt >> 32) & MIPSDSP_LLO;
2566
    rt0 = rt & MIPSDSP_LLO;
2567

    
2568
    tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);
2569
    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);
2570

    
2571
    if (tempB[0] >= 0) {
2572
        tempB[1] = 0x00;
2573
    } else {
2574
        tempB[1] = ~0ull;
2575
    }
2576

    
2577
    if (tempA[0] >= 0) {
2578
        tempA[1] = 0x00;
2579
    } else {
2580
        tempA[1] = ~0ull;
2581
    }
2582

    
2583
    acc[0] = env->active_tc.LO[ac];
2584
    acc[1] = env->active_tc.HI[ac];
2585

    
2586
    temp_sum = tempB[0] - tempA[0];
2587
    if ((uint64_t)temp_sum > (uint64_t)tempB[0]) {
2588
        tempB[1] -= 1;
2589
    }
2590
    temp[0] = temp_sum;
2591
    temp[1] = tempB[1] - tempA[1];
2592

    
2593
    if ((temp[1] & 0x01) == 0) {
2594
        temp[1] = 0x00;
2595
    } else {
2596
        temp[1] = ~0ull;
2597
    }
2598

    
2599
    temp_sum = acc[0] + temp[0];
2600
    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
2601
       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
2602
        acc[1] += 1;
2603
    }
2604
    acc[0] = temp_sum;
2605
    acc[1] += temp[1];
2606

    
2607
    env->active_tc.HI[ac] = acc[1];
2608
    env->active_tc.LO[ac] = acc[0];
2609
}
2610
#endif
2611

    
2612
#define MAQ_S_W(name, mov) \
2613
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
2614
                   CPUMIPSState *env)                             \
2615
{                                                                 \
2616
    int16_t rsh, rth;                                             \
2617
    int32_t tempA;                                                \
2618
    int64_t tempL, acc;                                           \
2619
                                                                  \
2620
    rsh = (rs >> mov) & MIPSDSP_LO;                               \
2621
    rth = (rt >> mov) & MIPSDSP_LO;                               \
2622
    tempA  = mipsdsp_mul_q15_q15(ac, rsh, rth, env);              \
2623
    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |               \
2624
          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);        \
2625
    tempL  = (int64_t)tempA + acc;                                \
2626
    env->active_tc.HI[ac] = (target_long)(int32_t)                \
2627
        ((tempL & MIPSDSP_LHI) >> 32);                            \
2628
    env->active_tc.LO[ac] = (target_long)(int32_t)                \
2629
        (tempL & MIPSDSP_LLO);                                    \
2630
}
2631

    
2632
MAQ_S_W(maq_s_w_phl, 16);
2633
MAQ_S_W(maq_s_w_phr, 0);
2634

    
2635
#undef MAQ_S_W
2636

    
2637
#define MAQ_SA_W(name, mov) \
2638
void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
2639
                   CPUMIPSState *env)                                    \
2640
{                                                                        \
2641
    int16_t rsh, rth;                                                    \
2642
    int32_t tempA;                                                       \
2643
                                                                         \
2644
    rsh = (rs >> mov) & MIPSDSP_LO;                                      \
2645
    rth = (rt >> mov) & MIPSDSP_LO;                                      \
2646
    tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                      \
2647
    tempA = mipsdsp_sat32_acc_q31(ac, tempA, env);                       \
2648
                                                                         \
2649
    env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA &     \
2650
                                                    MIPSDSP_LHI) >> 32); \
2651
    env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA &      \
2652
                                                   MIPSDSP_LLO);         \
2653
}
2654

    
2655
MAQ_SA_W(maq_sa_w_phl, 16);
2656
MAQ_SA_W(maq_sa_w_phr, 0);
2657

    
2658
#undef MAQ_SA_W
2659

    
2660
#define MULQ_W(name, addvar) \
2661
target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
2662
                           CPUMIPSState *env)                  \
2663
{                                                              \
2664
    int32_t rs_t, rt_t;                                        \
2665
    int32_t tempI;                                             \
2666
    int64_t tempL;                                             \
2667
                                                               \
2668
    rs_t = rs & MIPSDSP_LLO;                                   \
2669
    rt_t = rt & MIPSDSP_LLO;                                   \
2670
                                                               \
2671
    if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) {        \
2672
        tempL = 0x7FFFFFFF00000000ull;                         \
2673
        set_DSPControl_overflow_flag(1, 21, env);              \
2674
    } else {                                                   \
2675
        tempL  = ((int64_t)rs_t * (int64_t)rt_t) << 1;         \
2676
        tempL += addvar;                                       \
2677
    }                                                          \
2678
    tempI = (tempL & MIPSDSP_LHI) >> 32;                       \
2679
                                                               \
2680
    return (target_long)(int32_t)tempI;                        \
2681
}
2682

    
2683
MULQ_W(mulq_s_w, 0);
2684
MULQ_W(mulq_rs_w, 0x80000000ull);
2685

    
2686
#undef MULQ_W
2687

    
2688
#if defined(TARGET_MIPS64)
2689

    
2690
#define MAQ_S_W_QH(name, mov) \
2691
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2692
                   CPUMIPSState *env)                             \
2693
{                                                                 \
2694
    int16_t rs_t, rt_t;                                           \
2695
    int32_t temp_mul;                                             \
2696
    int64_t temp[2];                                              \
2697
    int64_t acc[2];                                               \
2698
    int64_t temp_sum;                                             \
2699
                                                                  \
2700
    temp[0] = 0;                                                  \
2701
    temp[1] = 0;                                                  \
2702
                                                                  \
2703
    rs_t = (rs >> mov) & MIPSDSP_LO;                              \
2704
    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
2705
    temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);          \
2706
                                                                  \
2707
    temp[0] = (int64_t)temp_mul;                                  \
2708
    if (temp[0] >= 0) {                                           \
2709
        temp[1] = 0x00;                                           \
2710
    } else {                                                      \
2711
        temp[1] = ~0ull;                                          \
2712
    }                                                             \
2713
                                                                  \
2714
    acc[0] = env->active_tc.LO[ac];                               \
2715
    acc[1] = env->active_tc.HI[ac];                               \
2716
                                                                  \
2717
    temp_sum = acc[0] + temp[0];                                  \
2718
    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&                \
2719
        ((uint64_t)temp_sum < (uint64_t)temp[0])) {               \
2720
        acc[1] += 1;                                              \
2721
    }                                                             \
2722
    acc[0] = temp_sum;                                            \
2723
    acc[1] += temp[1];                                            \
2724
                                                                  \
2725
    env->active_tc.HI[ac] = acc[1];                               \
2726
    env->active_tc.LO[ac] = acc[0];                               \
2727
}
2728

    
2729
MAQ_S_W_QH(maq_s_w_qhll, 48);
2730
MAQ_S_W_QH(maq_s_w_qhlr, 32);
2731
MAQ_S_W_QH(maq_s_w_qhrl, 16);
2732
MAQ_S_W_QH(maq_s_w_qhrr, 0);
2733

    
2734
#undef MAQ_S_W_QH
2735

    
2736
#define MAQ_SA_W(name, mov) \
2737
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2738
                   CPUMIPSState *env)                             \
2739
{                                                                 \
2740
    int16_t rs_t, rt_t;                                           \
2741
    int32_t temp;                                                 \
2742
    int64_t acc[2];                                               \
2743
                                                                  \
2744
    rs_t = (rs >> mov) & MIPSDSP_LO;                              \
2745
    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
2746
    temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);              \
2747
    temp = mipsdsp_sat32_acc_q31(ac, temp, env);                  \
2748
                                                                  \
2749
    acc[0] = (int64_t)(int32_t)temp;                              \
2750
    if (acc[0] >= 0) {                                            \
2751
        acc[1] = 0x00;                                            \
2752
    } else {                                                      \
2753
        acc[1] = ~0ull;                                           \
2754
    }                                                             \
2755
                                                                  \
2756
    env->active_tc.HI[ac] = acc[1];                               \
2757
    env->active_tc.LO[ac] = acc[0];                               \
2758
}
2759

    
2760
MAQ_SA_W(maq_sa_w_qhll, 48);
2761
MAQ_SA_W(maq_sa_w_qhlr, 32);
2762
MAQ_SA_W(maq_sa_w_qhrl, 16);
2763
MAQ_SA_W(maq_sa_w_qhrr, 0);
2764

    
2765
#undef MAQ_SA_W
2766

    
2767
#define MAQ_S_L_PW(name, mov) \
2768
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
2769
                   CPUMIPSState *env)                             \
2770
{                                                                 \
2771
    int32_t rs_t, rt_t;                                           \
2772
    int64_t temp[2];                                              \
2773
    int64_t acc[2];                                               \
2774
    int64_t temp_sum;                                             \
2775
                                                                  \
2776
    temp[0] = 0;                                                  \
2777
    temp[1] = 0;                                                  \
2778
                                                                  \
2779
    rs_t = (rs >> mov) & MIPSDSP_LLO;                             \
2780
    rt_t = (rt >> mov) & MIPSDSP_LLO;                             \
2781
                                                                  \
2782
    temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env);           \
2783
    if (temp[0] >= 0) {                                           \
2784
        temp[1] = 0x00;                                           \
2785
    } else {                                                      \
2786
        temp[1] = ~0ull;                                          \
2787
    }                                                             \
2788
                                                                  \
2789
    acc[0] = env->active_tc.LO[ac];                               \
2790
    acc[1] = env->active_tc.HI[ac];                               \
2791
                                                                  \
2792
    temp_sum = acc[0] + temp[0];                                  \
2793
    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&                \
2794
        ((uint64_t)temp_sum < (uint64_t)temp[0])) {               \
2795
        acc[1] += 1;                                              \
2796
    }                                                             \
2797
    acc[0] = temp_sum;                                            \
2798
    acc[1] += temp[1];                                            \
2799
                                                                  \
2800
    env->active_tc.HI[ac] = acc[1];                               \
2801
    env->active_tc.LO[ac] = acc[0];                               \
2802
}
2803

    
2804
MAQ_S_L_PW(maq_s_l_pwl, 32);
2805
MAQ_S_L_PW(maq_s_l_pwr, 0);
2806

    
2807
#undef MAQ_S_L_PW
2808

    
2809
#define DM_OPERATE(name, func, is_add, sigext) \
2810
void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
2811
                  CPUMIPSState *env)                                 \
2812
{                                                                    \
2813
    int32_t rs1, rs0;                                                \
2814
    int32_t rt1, rt0;                                                \
2815
    int64_t tempBL[2], tempAL[2];                                    \
2816
    int64_t acc[2];                                                  \
2817
    int64_t temp[2];                                                 \
2818
    int64_t temp_sum;                                                \
2819
                                                                     \
2820
    temp[0] = 0x00;                                                  \
2821
    temp[1] = 0x00;                                                  \
2822
                                                                     \
2823
    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                                \
2824
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                                \
2825
                                                                     \
2826
    if (sigext) {                                                    \
2827
        tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1);               \
2828
        tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0);               \
2829
                                                                     \
2830
        if (tempBL[0] >= 0) {                                        \
2831
            tempBL[1] = 0x0;                                         \
2832
        } else {                                                     \
2833
            tempBL[1] = ~0ull;                                       \
2834
        }                                                            \
2835
                                                                     \
2836
        if (tempAL[0] >= 0) {                                        \
2837
            tempAL[1] = 0x0;                                         \
2838
        } else {                                                     \
2839
            tempAL[1] = ~0ull;                                       \
2840
        }                                                            \
2841
    } else {                                                         \
2842
        tempBL[0] = mipsdsp_##func(rs1, rt1);                        \
2843
        tempAL[0] = mipsdsp_##func(rs0, rt0);                        \
2844
        tempBL[1] = 0;                                               \
2845
        tempAL[1] = 0;                                               \
2846
    }                                                                \
2847
                                                                     \
2848
    acc[1] = env->active_tc.HI[ac];                                  \
2849
    acc[0] = env->active_tc.LO[ac];                                  \
2850
                                                                     \
2851
    temp_sum = tempBL[0] + tempAL[0];                                \
2852
    if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) &&                \
2853
        ((uint64_t)temp_sum < (uint64_t)tempAL[0])) {                \
2854
        temp[1] += 1;                                                \
2855
    }                                                                \
2856
    temp[0] = temp_sum;                                              \
2857
    temp[1] += tempBL[1] + tempAL[1];                                \
2858
                                                                     \
2859
    if (is_add) {                                                    \
2860
        temp_sum = acc[0] + temp[0];                                 \
2861
        if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&               \
2862
            ((uint64_t)temp_sum < (uint64_t)temp[0])) {              \
2863
            acc[1] += 1;                                             \
2864
        }                                                            \
2865
        temp[0] = temp_sum;                                          \
2866
        temp[1] = acc[1] + temp[1];                                  \
2867
    } else {                                                         \
2868
        temp_sum = acc[0] - temp[0];                                 \
2869
        if ((uint64_t)temp_sum > (uint64_t)acc[0]) {                 \
2870
            acc[1] -= 1;                                             \
2871
        }                                                            \
2872
        temp[0] = temp_sum;                                          \
2873
        temp[1] = acc[1] - temp[1];                                  \
2874
    }                                                                \
2875
                                                                     \
2876
    env->active_tc.HI[ac] = temp[1];                                 \
2877
    env->active_tc.LO[ac] = temp[0];                                 \
2878
}
2879

    
2880
DM_OPERATE(dmadd, mul_i32_i32, 1, 1);
2881
DM_OPERATE(dmaddu, mul_u32_u32, 1, 0);
2882
DM_OPERATE(dmsub, mul_i32_i32, 0, 1);
2883
DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
2884
#undef DM_OPERATE
2885
#endif
2886

    
2887
/** DSP Bit/Manipulation Sub-class insns **/
2888
target_ulong helper_bitrev(target_ulong rt)
2889
{
2890
    int32_t temp;
2891
    uint32_t rd;
2892
    int i;
2893

    
2894
    temp = rt & MIPSDSP_LO;
2895
    rd = 0;
2896
    for (i = 0; i < 16; i++) {
2897
        rd = (rd << 1) | (temp & 1);
2898
        temp = temp >> 1;
2899
    }
2900

    
2901
    return (target_ulong)rd;
2902
}
2903

    
2904
#define BIT_INSV(name, posfilter, sizefilter, ret_type)         \
2905
target_ulong helper_##name(CPUMIPSState *env, target_ulong rs,  \
2906
                           target_ulong rt)                     \
2907
{                                                               \
2908
    uint32_t pos, size, msb, lsb;                               \
2909
    target_ulong filter;                                        \
2910
    target_ulong temp, temprs, temprt;                          \
2911
    target_ulong dspc;                                          \
2912
                                                                \
2913
    dspc = env->active_tc.DSPControl;                           \
2914
                                                                \
2915
    pos  = dspc & posfilter;                                    \
2916
    size = (dspc >> 7) & sizefilter;                            \
2917
                                                                \
2918
    msb  = pos + size - 1;                                      \
2919
    lsb  = pos;                                                 \
2920
                                                                \
2921
    if (lsb > msb || (msb > TARGET_LONG_BITS)) {                \
2922
        return rt;                                              \
2923
    }                                                           \
2924
                                                                \
2925
    filter = ((int64_t)0x01 << size) - 1;                       \
2926
    filter = filter << pos;                                     \
2927
    temprs = (rs << pos) & filter;                              \
2928
    temprt = rt & ~filter;                                      \
2929
    temp = temprs | temprt;                                     \
2930
                                                                \
2931
    return (target_long)(ret_type)temp;                         \
2932
}
2933

    
2934
BIT_INSV(insv, 0x1F, 0x3F, int32_t);
2935
#ifdef TARGET_MIPS64
2936
BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
2937
#endif
2938

    
2939
#undef BIT_INSV
2940

    
2941

    
2942
/** DSP Compare-Pick Sub-class insns **/
2943
#define CMP_HAS_RET(name, func, split_num, filter, bit_size) \
2944
target_ulong helper_##name(target_ulong rs, target_ulong rt) \
2945
{                                                       \
2946
    uint32_t rs_t, rt_t;                                \
2947
    uint8_t cc;                                         \
2948
    uint32_t temp = 0;                                  \
2949
    int i;                                              \
2950
                                                        \
2951
    for (i = 0; i < split_num; i++) {                   \
2952
        rs_t = (rs >> (bit_size * i)) & filter;         \
2953
        rt_t = (rt >> (bit_size * i)) & filter;         \
2954
        cc = mipsdsp_##func(rs_t, rt_t);                \
2955
        temp |= cc << i;                                \
2956
    }                                                   \
2957
                                                        \
2958
    return (target_ulong)temp;                          \
2959
}
2960

    
2961
CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
2962
CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
2963
CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
2964

    
2965
#ifdef TARGET_MIPS64
2966
CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
2967
CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
2968
CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
2969
#endif
2970

    
2971
#undef CMP_HAS_RET
2972

    
2973

    
2974
#define CMP_NO_RET(name, func, split_num, filter, bit_size) \
2975
void helper_##name(target_ulong rs, target_ulong rt,        \
2976
                            CPUMIPSState *env)              \
2977
{                                                           \
2978
    int##bit_size##_t rs_t, rt_t;                           \
2979
    int##bit_size##_t flag = 0;                             \
2980
    int##bit_size##_t cc;                                   \
2981
    int i;                                                  \
2982
                                                            \
2983
    for (i = 0; i < split_num; i++) {                       \
2984
        rs_t = (rs >> (bit_size * i)) & filter;             \
2985
        rt_t = (rt >> (bit_size * i)) & filter;             \
2986
                                                            \
2987
        cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t);  \
2988
        flag |= cc << i;                                    \
2989
    }                                                       \
2990
                                                            \
2991
    set_DSPControl_24(flag, split_num, env);                \
2992
}
2993

    
2994
CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
2995
CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
2996
CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
2997

    
2998
CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16);
2999
CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16);
3000
CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16);
3001

    
3002
#ifdef TARGET_MIPS64
3003
CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
3004
CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
3005
CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
3006

    
3007
CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16);
3008
CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16);
3009
CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16);
3010

    
3011
CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32);
3012
CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32);
3013
CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32);
3014
#endif
3015
#undef CMP_NO_RET
3016

    
3017
#if defined(TARGET_MIPS64)
3018

    
3019
#define CMPGDU_OB(name) \
3020
target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \
3021
                                       CPUMIPSState *env)  \
3022
{                                                     \
3023
    int i;                                            \
3024
    uint8_t rs_t, rt_t;                               \
3025
    uint32_t cond;                                    \
3026
                                                      \
3027
    cond = 0;                                         \
3028
                                                      \
3029
    for (i = 0; i < 8; i++) {                         \
3030
        rs_t = (rs >> (8 * i)) & MIPSDSP_Q0;          \
3031
        rt_t = (rt >> (8 * i)) & MIPSDSP_Q0;          \
3032
                                                      \
3033
        if (mipsdsp_cmpu_##name(rs_t, rt_t)) {        \
3034
            cond |= 0x01 << i;                        \
3035
        }                                             \
3036
    }                                                 \
3037
                                                      \
3038
    set_DSPControl_24(cond, 8, env);                  \
3039
                                                      \
3040
    return (uint64_t)cond;                            \
3041
}
3042

    
3043
CMPGDU_OB(eq)
3044
CMPGDU_OB(lt)
3045
CMPGDU_OB(le)
3046
#undef CMPGDU_OB
3047
#endif
3048

    
3049
#define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \
3050
target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
3051
                            CPUMIPSState *env)                 \
3052
{                                                              \
3053
    uint32_t rs_t, rt_t;                                       \
3054
    uint32_t cc;                                               \
3055
    target_ulong dsp;                                          \
3056
    int i;                                                     \
3057
    target_ulong result = 0;                                   \
3058
                                                               \
3059
    dsp = env->active_tc.DSPControl;                           \
3060
    for (i = 0; i < split_num; i++) {                          \
3061
        rs_t = (rs >> (bit_size * i)) & filter;                \
3062
        rt_t = (rt >> (bit_size * i)) & filter;                \
3063
        cc = (dsp >> (24 + i)) & 0x01;                         \
3064
        cc = cc == 1 ? rs_t : rt_t;                            \
3065
                                                               \
3066
        result |= (target_ulong)cc << (bit_size * i);          \
3067
    }                                                          \
3068
                                                               \
3069
    if (ret32bit) {                                            \
3070
        result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
3071
    }                                                          \
3072
                                                               \
3073
    return result;                                             \
3074
}
3075

    
3076
PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1);
3077
PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1);
3078

    
3079
#ifdef TARGET_MIPS64
3080
PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0);
3081
PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0);
3082
PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
3083
#endif
3084
#undef PICK_INSN
3085

    
3086
target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
3087
{
3088
    uint32_t rsl, rth;
3089

    
3090
    rsl =  rs & MIPSDSP_LO;
3091
    rth = (rt & MIPSDSP_HI) >> 16;
3092

    
3093
    return (target_long)(int32_t)((rsl << 16) | rth);
3094
}
3095

    
3096
#if defined(TARGET_MIPS64)
3097
target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
3098
{
3099
    uint32_t rs0, rt1;
3100

    
3101
    rs0 = rs & MIPSDSP_LLO;
3102
    rt1 = (rt >> 32) & MIPSDSP_LLO;
3103

    
3104
    return ((uint64_t)rs0 << 32) | (uint64_t)rt1;
3105
}
3106
#endif
3107

    
3108
/** DSP Accumulator and DSPControl Access Sub-class insns **/
3109
target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
3110
                           CPUMIPSState *env)
3111
{
3112
    int32_t tempI;
3113
    int64_t tempDL[2];
3114

    
3115
    shift = shift & 0x1F;
3116

    
3117
    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3118
    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3119
        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3120
        set_DSPControl_overflow_flag(1, 23, env);
3121
    }
3122

    
3123
    tempI = (tempDL[0] >> 1) & MIPSDSP_LLO;
3124

    
3125
    tempDL[0] += 1;
3126
    if (tempDL[0] == 0) {
3127
        tempDL[1] += 1;
3128
    }
3129

    
3130
    if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3131
        ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3132
        set_DSPControl_overflow_flag(1, 23, env);
3133
    }
3134

    
3135
    return (target_long)tempI;
3136
}
3137

    
3138
target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
3139
                             CPUMIPSState *env)
3140
{
3141
    int64_t tempDL[2];
3142

    
3143
    shift = shift & 0x1F;
3144

    
3145
    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3146
    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3147
        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3148
        set_DSPControl_overflow_flag(1, 23, env);
3149
    }
3150

    
3151
    tempDL[0] += 1;
3152
    if (tempDL[0] == 0) {
3153
        tempDL[1] += 1;
3154
    }
3155

    
3156
    if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3157
        ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3158
        set_DSPControl_overflow_flag(1, 23, env);
3159
    }
3160

    
3161
    return (target_long)(int32_t)(tempDL[0] >> 1);
3162
}
3163

    
3164
target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
3165
                              CPUMIPSState *env)
3166
{
3167
    int32_t tempI, temp64;
3168
    int64_t tempDL[2];
3169

    
3170
    shift = shift & 0x1F;
3171

    
3172
    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
3173
    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3174
        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3175
        set_DSPControl_overflow_flag(1, 23, env);
3176
    }
3177
    tempDL[0] += 1;
3178
    if (tempDL[0] == 0) {
3179
        tempDL[1] += 1;
3180
    }
3181
    tempI = tempDL[0] >> 1;
3182

    
3183
    if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
3184
        ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
3185
        temp64 = tempDL[1] & 0x01;
3186
        if (temp64 == 0) {
3187
            tempI = 0x7FFFFFFF;
3188
        } else {
3189
            tempI = 0x80000000;
3190
        }
3191
        set_DSPControl_overflow_flag(1, 23, env);
3192
    }
3193

    
3194
    return (target_long)tempI;
3195
}
3196

    
3197
#if defined(TARGET_MIPS64)
3198
target_ulong helper_dextr_w(target_ulong ac, target_ulong shift,
3199
                            CPUMIPSState *env)
3200
{
3201
    uint64_t temp[3];
3202

    
3203
    shift = shift & 0x3F;
3204

    
3205
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3206

    
3207
    return (int64_t)(int32_t)(temp[0] >> 1);
3208
}
3209

    
3210
target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift,
3211
                              CPUMIPSState *env)
3212
{
3213
    uint64_t temp[3];
3214
    uint32_t temp128;
3215

    
3216
    shift = shift & 0x3F;
3217
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3218

    
3219
    temp[0] += 1;
3220
    if (temp[0] == 0) {
3221
        temp[1] += 1;
3222
        if (temp[1] == 0) {
3223
            temp[2] += 1;
3224
        }
3225
    }
3226

    
3227
    temp128 = temp[2] & 0x01;
3228

    
3229
    if ((temp128 != 0 || temp[1] != 0) &&
3230
       (temp128 != 1 || temp[1] != ~0ull)) {
3231
        set_DSPControl_overflow_flag(1, 23, env);
3232
    }
3233

    
3234
    return (int64_t)(int32_t)(temp[0] >> 1);
3235
}
3236

    
3237
target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift,
3238
                               CPUMIPSState *env)
3239
{
3240
    uint64_t temp[3];
3241
    uint32_t temp128;
3242

    
3243
    shift = shift & 0x3F;
3244
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3245

    
3246
    temp[0] += 1;
3247
    if (temp[0] == 0) {
3248
        temp[1] += 1;
3249
        if (temp[1] == 0) {
3250
            temp[2] += 1;
3251
        }
3252
    }
3253

    
3254
    temp128 = temp[2] & 0x01;
3255

    
3256
    if ((temp128 != 0 || temp[1] != 0) &&
3257
       (temp128 != 1 || temp[1] != ~0ull)) {
3258
        if (temp128 == 0) {
3259
            temp[0] = 0x0FFFFFFFF;
3260
        } else {
3261
            temp[0] = 0x0100000000ULL;
3262
        }
3263
        set_DSPControl_overflow_flag(1, 23, env);
3264
    }
3265

    
3266
    return (int64_t)(int32_t)(temp[0] >> 1);
3267
}
3268

    
3269
target_ulong helper_dextr_l(target_ulong ac, target_ulong shift,
3270
                            CPUMIPSState *env)
3271
{
3272
    uint64_t temp[3];
3273
    target_ulong result;
3274

    
3275
    shift = shift & 0x3F;
3276

    
3277
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3278
    result = (temp[1] << 63) | (temp[0] >> 1);
3279

    
3280
    return result;
3281
}
3282

    
3283
target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift,
3284
                              CPUMIPSState *env)
3285
{
3286
    uint64_t temp[3];
3287
    uint32_t temp128;
3288
    target_ulong result;
3289

    
3290
    shift = shift & 0x3F;
3291
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3292

    
3293
    temp[0] += 1;
3294
    if (temp[0] == 0) {
3295
        temp[1] += 1;
3296
        if (temp[1] == 0) {
3297
            temp[2] += 1;
3298
        }
3299
    }
3300

    
3301
    temp128 = temp[2] & 0x01;
3302

    
3303
    if ((temp128 != 0 || temp[1] != 0) &&
3304
       (temp128 != 1 || temp[1] != ~0ull)) {
3305
        set_DSPControl_overflow_flag(1, 23, env);
3306
    }
3307

    
3308
    result = (temp[1] << 63) | (temp[0] >> 1);
3309

    
3310
    return result;
3311
}
3312

    
3313
target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
3314
                               CPUMIPSState *env)
3315
{
3316
    uint64_t temp[3];
3317
    uint32_t temp128;
3318
    target_ulong result;
3319

    
3320
    shift = shift & 0x3F;
3321
    mipsdsp_rndrashift_acc(temp, ac, shift, env);
3322

    
3323
    temp[0] += 1;
3324
    if (temp[0] == 0) {
3325
        temp[1] += 1;
3326
        if (temp[1] == 0) {
3327
            temp[2] += 1;
3328
        }
3329
    }
3330

    
3331
    temp128 = temp[2] & 0x01;
3332

    
3333
    if ((temp128 != 0 || temp[1] != 0) &&
3334
       (temp128 != 1 || temp[1] != ~0ull)) {
3335
        if (temp128 == 0) {
3336
            temp[1] &= ~0x00ull - 1;
3337
            temp[0] |= ~0x00ull - 1;
3338
        } else {
3339
            temp[1] |= 0x01;
3340
            temp[0] &= 0x01;
3341
        }
3342
        set_DSPControl_overflow_flag(1, 23, env);
3343
    }
3344
    result = (temp[1] << 63) | (temp[0] >> 1);
3345

    
3346
    return result;
3347
}
3348
#endif
3349

    
3350
target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
3351
                             CPUMIPSState *env)
3352
{
3353
    int64_t temp, acc;
3354

    
3355
    shift = shift & 0x1F;
3356

    
3357
    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
3358
          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
3359

    
3360
    temp = acc >> shift;
3361

    
3362
    if (temp > (int64_t)0x7FFF) {
3363
        temp = 0x00007FFF;
3364
        set_DSPControl_overflow_flag(1, 23, env);
3365
    } else if (temp < (int64_t)0xFFFFFFFFFFFF8000ULL) {
3366
        temp = 0xFFFF8000;
3367
        set_DSPControl_overflow_flag(1, 23, env);
3368
    }
3369

    
3370
    return (target_long)(int32_t)(temp & 0xFFFFFFFF);
3371
}
3372

    
3373

    
3374
#if defined(TARGET_MIPS64)
3375
target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift,
3376
                              CPUMIPSState *env)
3377
{
3378
    int64_t temp[2];
3379
    uint32_t temp127;
3380

    
3381
    shift = shift & 0x1F;
3382

    
3383
    mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env);
3384

    
3385
    temp127 = (temp[1] >> 63) & 0x01;
3386

    
3387
    if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
3388
        temp[0] &= 0xFFFF0000;
3389
        temp[0] |= 0x00007FFF;
3390
        set_DSPControl_overflow_flag(1, 23, env);
3391
    } else if ((temp127 == 1) &&
3392
            (temp[1] < 0xFFFFFFFFFFFFFFFFll
3393
             || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
3394
        temp[0] &= 0xFFFF0000;
3395
        temp[0] |= 0x00008000;
3396
        set_DSPControl_overflow_flag(1, 23, env);
3397
    }
3398

    
3399
    return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
3400
}
3401

    
3402
#endif
3403

    
3404
target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3405
{
3406
    int32_t start_pos;
3407
    int sub;
3408
    uint32_t temp;
3409
    uint64_t acc;
3410

    
3411
    size = size & 0x1F;
3412

    
3413
    temp = 0;
3414
    start_pos = get_DSPControl_pos(env);
3415
    sub = start_pos - (size + 1);
3416
    if (sub >= -1) {
3417
        acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
3418
              ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3419
        temp = (acc >> (start_pos - size)) & (~0U >> (31 - size));
3420
        set_DSPControl_efi(0, env);
3421
    } else {
3422
        set_DSPControl_efi(1, env);
3423
    }
3424

    
3425
    return (target_ulong)temp;
3426
}
3427

    
3428
target_ulong helper_extpdp(target_ulong ac, target_ulong size,
3429
                           CPUMIPSState *env)
3430
{
3431
    int32_t start_pos;
3432
    int sub;
3433
    uint32_t temp;
3434
    uint64_t acc;
3435

    
3436
    size = size & 0x1F;
3437
    temp = 0;
3438
    start_pos = get_DSPControl_pos(env);
3439
    sub = start_pos - (size + 1);
3440
    if (sub >= -1) {
3441
        acc  = ((uint64_t)env->active_tc.HI[ac] << 32) |
3442
               ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3443
        temp = extract64(acc, start_pos - size, size + 1);
3444

    
3445
        set_DSPControl_pos(sub, env);
3446
        set_DSPControl_efi(0, env);
3447
    } else {
3448
        set_DSPControl_efi(1, env);
3449
    }
3450

    
3451
    return (target_ulong)temp;
3452
}
3453

    
3454

    
3455
#if defined(TARGET_MIPS64)
3456
target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env)
3457
{
3458
    int start_pos;
3459
    int len;
3460
    int sub;
3461
    uint64_t tempB, tempA;
3462
    uint64_t temp;
3463

    
3464
    temp = 0;
3465

    
3466
    size = size & 0x3F;
3467
    start_pos = get_DSPControl_pos(env);
3468
    len = start_pos - size;
3469
    tempB = env->active_tc.HI[ac];
3470
    tempA = env->active_tc.LO[ac];
3471

    
3472
    sub = start_pos - (size + 1);
3473

    
3474
    if (sub >= -1) {
3475
        temp = (tempB << (64 - len)) | (tempA >> len);
3476
        temp = temp & ((0x01 << (size + 1)) - 1);
3477
        set_DSPControl_efi(0, env);
3478
    } else {
3479
        set_DSPControl_efi(1, env);
3480
    }
3481

    
3482
    return temp;
3483
}
3484

    
3485
target_ulong helper_dextpdp(target_ulong ac, target_ulong size,
3486
                            CPUMIPSState *env)
3487
{
3488
    int start_pos;
3489
    int len;
3490
    int sub;
3491
    uint64_t tempB, tempA;
3492
    uint64_t temp;
3493

    
3494
    temp = 0;
3495
    size = size & 0x3F;
3496
    start_pos = get_DSPControl_pos(env);
3497
    len = start_pos - size;
3498
    tempB = env->active_tc.HI[ac];
3499
    tempA = env->active_tc.LO[ac];
3500

    
3501
    sub = start_pos - (size + 1);
3502

    
3503
    if (sub >= -1) {
3504
        temp = (tempB << (64 - len)) | (tempA >> len);
3505
        temp = temp & ((0x01 << (size + 1)) - 1);
3506
        set_DSPControl_pos(sub, env);
3507
        set_DSPControl_efi(0, env);
3508
    } else {
3509
        set_DSPControl_efi(1, env);
3510
    }
3511

    
3512
    return temp;
3513
}
3514

    
3515
#endif
3516

    
3517
void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3518
{
3519
    int8_t  rs5_0;
3520
    uint64_t temp, acc;
3521

    
3522
    rs5_0 = rs & 0x3F;
3523
    rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
3524

    
3525
    if (unlikely(rs5_0 == 0)) {
3526
        return;
3527
    }
3528

    
3529
    acc   = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
3530
            ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
3531

    
3532
    if (rs5_0 > 0) {
3533
        temp = acc >> rs5_0;
3534
    } else {
3535
        temp = acc << -rs5_0;
3536
    }
3537

    
3538
    env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32);
3539
    env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO);
3540
}
3541

    
3542
#if defined(TARGET_MIPS64)
3543
void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env)
3544
{
3545
    int8_t shift_t;
3546
    uint64_t tempB, tempA;
3547

    
3548
    shift_t = (int8_t)(shift << 1) >> 1;
3549

    
3550
    tempB = env->active_tc.HI[ac];
3551
    tempA = env->active_tc.LO[ac];
3552

    
3553
    if (shift_t != 0) {
3554
        if (shift_t >= 0) {
3555
            tempA = (tempB << (64 - shift_t)) | (tempA >> shift_t);
3556
            tempB = tempB >> shift_t;
3557
        } else {
3558
            shift_t = -shift_t;
3559
            tempB = (tempB << shift_t) | (tempA >> (64 - shift_t));
3560
            tempA = tempA << shift_t;
3561
        }
3562
    }
3563

    
3564
    env->active_tc.HI[ac] = tempB;
3565
    env->active_tc.LO[ac] = tempA;
3566
}
3567

    
3568
#endif
3569
void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env)
3570
{
3571
    int32_t tempA, tempB, pos;
3572

    
3573
    tempA = rs;
3574
    tempB = env->active_tc.LO[ac];
3575
    env->active_tc.HI[ac] = (target_long)tempB;
3576
    env->active_tc.LO[ac] = (target_long)tempA;
3577
    pos = get_DSPControl_pos(env);
3578

    
3579
    if (pos > 32) {
3580
        return;
3581
    } else {
3582
        set_DSPControl_pos(pos + 32, env);
3583
    }
3584
}
3585

    
3586
#if defined(TARGET_MIPS64)
3587
void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
3588
{
3589
    uint8_t ac_t;
3590
    uint8_t pos;
3591
    uint64_t tempB, tempA;
3592

    
3593
    ac_t = ac & 0x3;
3594

    
3595
    tempA = rs;
3596
    tempB = env->active_tc.LO[ac_t];
3597

    
3598
    env->active_tc.HI[ac_t] = tempB;
3599
    env->active_tc.LO[ac_t] = tempA;
3600

    
3601
    pos = get_DSPControl_pos(env);
3602

    
3603
    if (pos <= 64) {
3604
        pos = pos + 64;
3605
        set_DSPControl_pos(pos, env);
3606
    }
3607
}
3608
#endif
3609

    
3610
void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env)
3611
{
3612
    uint8_t  mask[6];
3613
    uint8_t  i;
3614
    uint32_t newbits, overwrite;
3615
    target_ulong dsp;
3616

    
3617
    newbits   = 0x00;
3618
    overwrite = 0xFFFFFFFF;
3619
    dsp = env->active_tc.DSPControl;
3620

    
3621
    for (i = 0; i < 6; i++) {
3622
        mask[i] = (mask_num >> i) & 0x01;
3623
    }
3624

    
3625
    if (mask[0] == 1) {
3626
#if defined(TARGET_MIPS64)
3627
        overwrite &= 0xFFFFFF80;
3628
        newbits   &= 0xFFFFFF80;
3629
        newbits   |= 0x0000007F & rs;
3630
#else
3631
        overwrite &= 0xFFFFFFC0;
3632
        newbits   &= 0xFFFFFFC0;
3633
        newbits   |= 0x0000003F & rs;
3634
#endif
3635
    }
3636

    
3637
    if (mask[1] == 1) {
3638
        overwrite &= 0xFFFFE07F;
3639
        newbits   &= 0xFFFFE07F;
3640
        newbits   |= 0x00001F80 & rs;
3641
    }
3642

    
3643
    if (mask[2] == 1) {
3644
        overwrite &= 0xFFFFDFFF;
3645
        newbits   &= 0xFFFFDFFF;
3646
        newbits   |= 0x00002000 & rs;
3647
    }
3648

    
3649
    if (mask[3] == 1) {
3650
        overwrite &= 0xFF00FFFF;
3651
        newbits   &= 0xFF00FFFF;
3652
        newbits   |= 0x00FF0000 & rs;
3653
    }
3654

    
3655
    if (mask[4] == 1) {
3656
        overwrite &= 0x00FFFFFF;
3657
        newbits   &= 0x00FFFFFF;
3658
#if defined(TARGET_MIPS64)
3659
        newbits   |= 0xFF000000 & rs;
3660
#else
3661
        newbits   |= 0x0F000000 & rs;
3662
#endif
3663
    }
3664

    
3665
    if (mask[5] == 1) {
3666
        overwrite &= 0xFFFFBFFF;
3667
        newbits   &= 0xFFFFBFFF;
3668
        newbits   |= 0x00004000 & rs;
3669
    }
3670

    
3671
    dsp = dsp & overwrite;
3672
    dsp = dsp | newbits;
3673
    env->active_tc.DSPControl = dsp;
3674
}
3675

    
3676
void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
3677
{
3678
    return cpu_wrdsp(rs, mask_num, env);
3679
}
3680

    
3681
uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env)
3682
{
3683
    uint8_t  mask[6];
3684
    uint32_t ruler, i;
3685
    target_ulong temp;
3686
    target_ulong dsp;
3687

    
3688
    ruler = 0x01;
3689
    for (i = 0; i < 6; i++) {
3690
        mask[i] = (mask_num & ruler) >> i ;
3691
        ruler = ruler << 1;
3692
    }
3693

    
3694
    temp  = 0x00;
3695
    dsp = env->active_tc.DSPControl;
3696

    
3697
    if (mask[0] == 1) {
3698
#if defined(TARGET_MIPS64)
3699
        temp |= dsp & 0x7F;
3700
#else
3701
        temp |= dsp & 0x3F;
3702
#endif
3703
    }
3704

    
3705
    if (mask[1] == 1) {
3706
        temp |= dsp & 0x1F80;
3707
    }
3708

    
3709
    if (mask[2] == 1) {
3710
        temp |= dsp & 0x2000;
3711
    }
3712

    
3713
    if (mask[3] == 1) {
3714
        temp |= dsp & 0x00FF0000;
3715
    }
3716

    
3717
    if (mask[4] == 1) {
3718
#if defined(TARGET_MIPS64)
3719
        temp |= dsp & 0xFF000000;
3720
#else
3721
        temp |= dsp & 0x0F000000;
3722
#endif
3723
    }
3724

    
3725
    if (mask[5] == 1) {
3726
        temp |= dsp & 0x4000;
3727
    }
3728

    
3729
    return temp;
3730
}
3731

    
3732
target_ulong helper_rddsp(target_ulong mask_num, CPUMIPSState *env)
3733
{
3734
    return cpu_rddsp(mask_num, env);
3735
}
3736

    
3737

    
3738
#undef MIPSDSP_LHI
3739
#undef MIPSDSP_LLO
3740
#undef MIPSDSP_HI
3741
#undef MIPSDSP_LO
3742
#undef MIPSDSP_Q3
3743
#undef MIPSDSP_Q2
3744
#undef MIPSDSP_Q1
3745
#undef MIPSDSP_Q0
3746

    
3747
#undef MIPSDSP_SPLIT32_8
3748
#undef MIPSDSP_SPLIT32_16
3749

    
3750
#undef MIPSDSP_RETURN32_8
3751
#undef MIPSDSP_RETURN32_16
3752

    
3753
#ifdef TARGET_MIPS64
3754
#undef MIPSDSP_SPLIT64_16
3755
#undef MIPSDSP_SPLIT64_32
3756
#undef MIPSDSP_RETURN64_16
3757
#undef MIPSDSP_RETURN64_32
3758
#endif