Statistics
| Branch: | Revision:

root / target-mips / dsp_helper.c @ 77c5fa8b

History | View | Annotate | Download (68.3 kB)

1
/*
2
 * MIPS ASE DSP Instruction emulation helpers for QEMU.
3
 *
4
 * Copyright (c) 2012  Jia Liu <proljc@gmail.com>
5
 *                     Dongxue Zhang <elat.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

    
23
/*** MIPS DSP internal functions begin ***/
24
#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
25
#define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d)))
26

    
27
static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
28
                                                CPUMIPSState *env)
29
{
30
    env->active_tc.DSPControl |= (target_ulong)flag << position;
31
}
32

    
33
static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
34
{
35
    env->active_tc.DSPControl |= (target_ulong)flag << 13;
36
}
37

    
38
static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
39
{
40
    return (env->active_tc.DSPControl >> 13) & 0x01;
41
}
42

    
43
static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
44
{
45
  uint32_t filter;
46

    
47
  filter = ((0x01 << len) - 1) << 24;
48
  filter = ~filter;
49

    
50
  env->active_tc.DSPControl &= filter;
51
  env->active_tc.DSPControl |= (target_ulong)flag << 24;
52
}
53

    
54
static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env)
55
{
56
  uint32_t filter;
57

    
58
  filter = (0x01 << len) - 1;
59

    
60
  return (env->active_tc.DSPControl >> 24) & filter;
61
}
62

    
63
static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
64
{
65
    target_ulong dspc;
66

    
67
    dspc = env->active_tc.DSPControl;
68
#ifndef TARGET_MIPS64
69
    dspc = dspc & 0xFFFFFFC0;
70
    dspc |= pos;
71
#else
72
    dspc = dspc & 0xFFFFFF80;
73
    dspc |= pos;
74
#endif
75
    env->active_tc.DSPControl = dspc;
76
}
77

    
78
static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
79
{
80
    target_ulong dspc;
81
    uint32_t pos;
82

    
83
    dspc = env->active_tc.DSPControl;
84

    
85
#ifndef TARGET_MIPS64
86
    pos = dspc & 0x3F;
87
#else
88
    pos = dspc & 0x7F;
89
#endif
90

    
91
    return pos;
92
}
93

    
94
static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env)
95
{
96
    env->active_tc.DSPControl &= 0xFFFFBFFF;
97
    env->active_tc.DSPControl |= (target_ulong)flag << 14;
98
}
99

    
100
#define DO_MIPS_SAT_ABS(size)                                          \
101
static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a,         \
102
                                                  CPUMIPSState *env)   \
103
{                                                                      \
104
    if (a == INT##size##_MIN) {                                        \
105
        set_DSPControl_overflow_flag(1, 20, env);                      \
106
        return INT##size##_MAX;                                        \
107
    } else {                                                           \
108
        return MIPSDSP_ABS(a);                                         \
109
    }                                                                  \
110
}
111
DO_MIPS_SAT_ABS(8)
112
DO_MIPS_SAT_ABS(16)
113
DO_MIPS_SAT_ABS(32)
114
#undef DO_MIPS_SAT_ABS
115

    
116
/* get sum value */
117
static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
118
{
119
    int16_t tempI;
120

    
121
    tempI = a + b;
122

    
123
    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) {
124
        set_DSPControl_overflow_flag(1, 20, env);
125
    }
126

    
127
    return tempI;
128
}
129

    
130
static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
131
                                          CPUMIPSState *env)
132
{
133
    int16_t tempS;
134

    
135
    tempS = a + b;
136

    
137
    if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) {
138
        if (a > 0) {
139
            tempS = 0x7FFF;
140
        } else {
141
            tempS = 0x8000;
142
        }
143
        set_DSPControl_overflow_flag(1, 20, env);
144
    }
145

    
146
    return tempS;
147
}
148

    
149
static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
150
                                          CPUMIPSState *env)
151
{
152
    int32_t tempI;
153

    
154
    tempI = a + b;
155

    
156
    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) {
157
        if (a > 0) {
158
            tempI = 0x7FFFFFFF;
159
        } else {
160
            tempI = 0x80000000;
161
        }
162
        set_DSPControl_overflow_flag(1, 20, env);
163
    }
164

    
165
    return tempI;
166
}
167

    
168
static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
169
{
170
    uint16_t temp;
171

    
172
    temp = (uint16_t)a + (uint16_t)b;
173

    
174
    if (temp & 0x0100) {
175
        set_DSPControl_overflow_flag(1, 20, env);
176
    }
177

    
178
    return temp & 0xFF;
179
}
180

    
181
static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b,
182
                                       CPUMIPSState *env)
183
{
184
    uint32_t temp;
185

    
186
    temp = (uint32_t)a + (uint32_t)b;
187

    
188
    if (temp & 0x00010000) {
189
        set_DSPControl_overflow_flag(1, 20, env);
190
    }
191

    
192
    return temp & 0xFFFF;
193
}
194

    
195
static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b,
196
                                         CPUMIPSState *env)
197
{
198
    uint8_t  result;
199
    uint16_t temp;
200

    
201
    temp = (uint16_t)a + (uint16_t)b;
202
    result = temp & 0xFF;
203

    
204
    if (0x0100 & temp) {
205
        result = 0xFF;
206
        set_DSPControl_overflow_flag(1, 20, env);
207
    }
208

    
209
    return result;
210
}
211

    
212
static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b,
213
                                           CPUMIPSState *env)
214
{
215
    uint16_t result;
216
    uint32_t temp;
217

    
218
    temp = (uint32_t)a + (uint32_t)b;
219
    result = temp & 0xFFFF;
220

    
221
    if (0x00010000 & temp) {
222
        result = 0xFFFF;
223
        set_DSPControl_overflow_flag(1, 20, env);
224
    }
225

    
226
    return result;
227
}
228

    
229
static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
230
                                            CPUMIPSState *env)
231
{
232
    int64_t temp;
233
    int32_t temp32, temp31, result;
234
    int64_t temp_sum;
235

    
236
#ifndef TARGET_MIPS64
237
    temp = ((uint64_t)env->active_tc.HI[acc] << 32) |
238
           (uint64_t)env->active_tc.LO[acc];
239
#else
240
    temp = (uint64_t)env->active_tc.LO[acc];
241
#endif
242

    
243
    temp_sum = (int64_t)a + temp;
244

    
245
    temp32 = (temp_sum >> 32) & 0x01;
246
    temp31 = (temp_sum >> 31) & 0x01;
247
    result = temp_sum & 0xFFFFFFFF;
248

    
249
    /* FIXME
250
       This sat function may wrong, because user manual wrote:
251
       temp127..0 ← temp + ( (signA) || a31..0
252
       if ( temp32 ≠ temp31 ) then
253
           if ( temp32 = 0 ) then
254
               temp31..0 ← 0x80000000
255
           else
256
                temp31..0 ← 0x7FFFFFFF
257
           endif
258
           DSPControlouflag:16+acc ← 1
259
       endif
260
     */
261
    if (temp32 != temp31) {
262
        if (temp32 == 0) {
263
            result = 0x7FFFFFFF;
264
        } else {
265
            result = 0x80000000;
266
        }
267
        set_DSPControl_overflow_flag(1, 16 + acc, env);
268
    }
269

    
270
    return result;
271
}
272

    
273
/* a[0] is LO, a[1] is HI. */
274
static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
275
                                             int32_t ac,
276
                                             int64_t *a,
277
                                             CPUMIPSState *env)
278
{
279
    bool temp64;
280

    
281
    ret[0] = env->active_tc.LO[ac] + a[0];
282
    ret[1] = env->active_tc.HI[ac] + a[1];
283

    
284
    if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) &&
285
        ((uint64_t)ret[0] < (uint64_t)a[0])) {
286
        ret[1] += 1;
287
    }
288
    temp64 = ret[1] & 1;
289
    if (temp64 != ((ret[0] >> 63) & 0x01)) {
290
        if (temp64) {
291
            ret[0] = (0x01ull << 63);
292
            ret[1] = ~0ull;
293
        } else {
294
            ret[0] = (0x01ull << 63) - 1;
295
            ret[1] = 0x00;
296
        }
297
        set_DSPControl_overflow_flag(1, 16 + ac, env);
298
    }
299
}
300

    
301
static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
302
                                             int32_t ac,
303
                                             int64_t *a,
304
                                             CPUMIPSState *env)
305
{
306
    bool temp64;
307

    
308
    ret[0] = env->active_tc.LO[ac] - a[0];
309
    ret[1] = env->active_tc.HI[ac] - a[1];
310

    
311
    if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) {
312
        ret[1] -= 1;
313
    }
314
    temp64 = ret[1] & 1;
315
    if (temp64 != ((ret[0] >> 63) & 0x01)) {
316
        if (temp64) {
317
            ret[0] = (0x01ull << 63);
318
            ret[1] = ~0ull;
319
        } else {
320
            ret[0] = (0x01ull << 63) - 1;
321
            ret[1] = 0x00;
322
        }
323
        set_DSPControl_overflow_flag(1, 16 + ac, env);
324
    }
325
}
326

    
327
static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
328
                                          CPUMIPSState *env)
329
{
330
    int32_t temp;
331

    
332
    temp = (int32_t)a * (int32_t)b;
333

    
334
    if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) {
335
        set_DSPControl_overflow_flag(1, 21, env);
336
    }
337
    temp &= 0x0000FFFF;
338

    
339
    return temp;
340
}
341

    
342
static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
343
{
344
    return a * b;
345
}
346

    
347
static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
348
{
349
    return a * b;
350
}
351

    
352
static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
353
                                                CPUMIPSState *env)
354
{
355
    int32_t temp;
356

    
357
    temp = (int32_t)a * (int32_t)b;
358

    
359
    if (temp > (int)0x7FFF) {
360
        temp = 0x00007FFF;
361
        set_DSPControl_overflow_flag(1, 21, env);
362
    } else if (temp < (int)0xffff8000) {
363
        temp = 0xFFFF8000;
364
        set_DSPControl_overflow_flag(1, 21, env);
365
    }
366
    temp &= 0x0000FFFF;
367

    
368
    return temp;
369
}
370

    
371
static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b,
372
                                                         CPUMIPSState *env)
373
{
374
    int32_t temp;
375

    
376
    if ((a == 0x8000) && (b == 0x8000)) {
377
        temp = 0x7FFFFFFF;
378
        set_DSPControl_overflow_flag(1, 21, env);
379
    } else {
380
        temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
381
    }
382

    
383
    return temp;
384
}
385

    
386
/* right shift */
387
static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov)
388
{
389
    return a >> mov;
390
}
391

    
392
static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov)
393
{
394
    return a >> mov;
395
}
396

    
397
static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov)
398
{
399
    return a >> mov;
400
}
401

    
402
static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
403
{
404
    return a >> mov;
405
}
406

    
407
static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
408
{
409
    return a >> mov;
410
}
411

    
412
static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
413
{
414
    int32_t temp;
415

    
416
    temp = (int32_t)a + (int32_t)b;
417

    
418
    return (temp >> 1) & 0xFFFF;
419
}
420

    
421
/* round right shift */
422
static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
423
{
424
    int32_t temp;
425

    
426
    temp = (int32_t)a + (int32_t)b;
427
    temp += 1;
428

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

    
432
static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
433
{
434
    int64_t temp;
435

    
436
    temp = (int64_t)a + (int64_t)b;
437

    
438
    return (temp >> 1) & 0xFFFFFFFF;
439
}
440

    
441
static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
442
{
443
    int64_t temp;
444

    
445
    temp = (int64_t)a + (int64_t)b;
446
    temp += 1;
447

    
448
    return (temp >> 1) & 0xFFFFFFFF;
449
}
450

    
451
static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
452
{
453
    uint16_t temp;
454

    
455
    temp = (uint16_t)a + (uint16_t)b;
456

    
457
    return (temp >> 1) & 0x00FF;
458
}
459

    
460
static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
461
{
462
    uint16_t temp;
463

    
464
    temp = (uint16_t)a + (uint16_t)b + 1;
465

    
466
    return (temp >> 1) & 0x00FF;
467
}
468

    
469
static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
470
{
471
    uint16_t temp;
472

    
473
    temp = (uint16_t)a - (uint16_t)b;
474

    
475
    return (temp >> 1) & 0x00FF;
476
}
477

    
478
static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
479
{
480
    uint16_t temp;
481

    
482
    temp = (uint16_t)a - (uint16_t)b + 1;
483

    
484
    return (temp >> 1) & 0x00FF;
485
}
486

    
487
static inline int64_t mipsdsp_rashift_short_acc(int32_t ac,
488
                                                int32_t shift,
489
                                                CPUMIPSState *env)
490
{
491
    int32_t sign, temp31;
492
    int64_t temp, acc;
493

    
494
    sign = (env->active_tc.HI[ac] >> 31) & 0x01;
495
    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
496
          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
497
    if (shift == 0) {
498
        temp = acc;
499
    } else {
500
        if (sign == 0) {
501
            temp = (((int64_t)0x01 << (32 - shift + 1)) - 1) & (acc >> shift);
502
        } else {
503
            temp = ((((int64_t)0x01 << (shift + 1)) - 1) << (32 - shift)) |
504
                   (acc >> shift);
505
        }
506
    }
507

    
508
    temp31 = (temp >> 31) & 0x01;
509
    if (sign != temp31) {
510
        set_DSPControl_overflow_flag(1, 23, env);
511
    }
512

    
513
    return temp;
514
}
515

    
516
/*  128 bits long. p[0] is LO, p[1] is HI. */
517
static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
518
                                                int32_t ac,
519
                                                int32_t shift,
520
                                                CPUMIPSState *env)
521
{
522
    int64_t acc;
523

    
524
    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
525
          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
526
    if (shift == 0) {
527
        p[0] = acc << 1;
528
        p[1] = (acc >> 63) & 0x01;
529
    } else {
530
        p[0] = acc >> (shift - 1);
531
        p[1] = 0;
532
    }
533
}
534

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

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

    
547
    if (shift == 0) {
548
        p[1] = tempB;
549
        p[0] = tempA;
550
    } else {
551
        p[0] = (tempB << (64 - shift)) | (tempA >> shift);
552
        p[1] = (int64_t)tempB >> shift;
553
    }
554
}
555

    
556
/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
557
static inline void mipsdsp_rndrashift_acc(uint64_t *p,
558
                                          uint32_t ac,
559
                                          uint32_t shift,
560
                                          CPUMIPSState *env)
561
{
562
    int64_t tempB, tempA;
563

    
564
    tempB = env->active_tc.HI[ac];
565
    tempA = env->active_tc.LO[ac];
566
    shift = shift & 0x3F;
567

    
568
    if (shift == 0) {
569
        p[2] = tempB >> 63;
570
        p[1] = (tempB << 1) | (tempA >> 63);
571
        p[0] = tempA << 1;
572
    } else {
573
        p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1));
574
        p[1] = (int64_t)tempB >> (shift - 1);
575
        if (tempB >= 0) {
576
            p[2] = 0x0;
577
        } else {
578
            p[2] = ~0ull;
579
        }
580
    }
581
}
582

    
583
static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
584
                                          CPUMIPSState *env)
585
{
586
    int32_t temp;
587

    
588
    if ((a == 0x8000) && (b == 0x8000)) {
589
        temp = 0x7FFFFFFF;
590
        set_DSPControl_overflow_flag(1, 16 + ac, env);
591
    } else {
592
        temp = ((uint32_t)a * (uint32_t)b) << 1;
593
    }
594

    
595
    return temp;
596
}
597

    
598
static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b,
599
                                          CPUMIPSState *env)
600
{
601
    uint64_t temp;
602

    
603
    if ((a == 0x80000000) && (b == 0x80000000)) {
604
        temp = (0x01ull << 63) - 1;
605
        set_DSPControl_overflow_flag(1, 16 + ac, env);
606
    } else {
607
        temp = ((uint64_t)a * (uint64_t)b) << 1;
608
    }
609

    
610
    return temp;
611
}
612

    
613
static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
614
{
615
    return (uint16_t)a * (uint16_t)b;
616
}
617

    
618
static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
619
                                          CPUMIPSState *env)
620
{
621
    uint32_t tempI;
622

    
623
    tempI = (uint32_t)a * (uint32_t)b;
624
    if (tempI > 0x0000FFFF) {
625
        tempI = 0x0000FFFF;
626
        set_DSPControl_overflow_flag(1, 21, env);
627
    }
628

    
629
    return tempI & 0x0000FFFF;
630
}
631

    
632
static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
633
{
634
    return (uint64_t)a * (uint64_t)b;
635
}
636

    
637
static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
638
                                                 CPUMIPSState *env)
639
{
640
    uint32_t temp;
641

    
642
    if ((a == 0x8000) && (b == 0x8000)) {
643
        temp = 0x7FFF0000;
644
        set_DSPControl_overflow_flag(1, 21, env);
645
    } else {
646
        temp = (a * b) << 1;
647
        temp = temp + 0x00008000;
648
    }
649

    
650
    return (temp & 0xFFFF0000) >> 16;
651
}
652

    
653
static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
654
                                                CPUMIPSState *env)
655
{
656
    int32_t temp;
657

    
658
    if ((a == 0x8000) && (b == 0x8000)) {
659
        temp = 0x7FFF0000;
660
        set_DSPControl_overflow_flag(1, 21, env);
661
    } else {
662
        temp = ((uint32_t)a * (uint32_t)b);
663
        temp = temp << 1;
664
    }
665

    
666
    return (temp >> 16) & 0x0000FFFF;
667
}
668

    
669
static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
670
                                                   CPUMIPSState *env)
671
{
672
    int64_t temp;
673

    
674
    temp = (int32_t)a + 0x00008000;
675

    
676
    if (a > (int)0x7fff8000) {
677
        temp = 0x7FFFFFFF;
678
        set_DSPControl_overflow_flag(1, 22, env);
679
    }
680

    
681
    return (temp >> 16) & 0xFFFF;
682
}
683

    
684
static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
685
                                                    CPUMIPSState *env)
686
{
687
    uint16_t mag;
688
    uint32_t sign;
689

    
690
    sign = (a >> 15) & 0x01;
691
    mag = a & 0x7FFF;
692

    
693
    if (sign == 0) {
694
        if (mag > 0x7F80) {
695
            set_DSPControl_overflow_flag(1, 22, env);
696
            return 0xFF;
697
        } else {
698
            return (mag >> 7) & 0xFFFF;
699
        }
700
    } else {
701
        set_DSPControl_overflow_flag(1, 22, env);
702
        return 0x00;
703
    }
704
}
705

    
706
static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
707
{
708
    uint8_t sign;
709
    uint8_t discard;
710

    
711
    if (s == 0) {
712
        return a;
713
    } else {
714
        sign = (a >> 7) & 0x01;
715
        if (sign != 0) {
716
            discard = (((0x01 << (8 - s)) - 1) << s) |
717
                      ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
718
        } else {
719
            discard = a >> (6 - (s - 1));
720
        }
721

    
722
        if (discard != 0x00) {
723
            set_DSPControl_overflow_flag(1, 22, env);
724
        }
725
        return a << s;
726
    }
727
}
728

    
729
static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
730
                                        CPUMIPSState *env)
731
{
732
    uint8_t  sign;
733
    uint16_t discard;
734

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

    
746
        if ((discard != 0x0000) && (discard != 0xFFFF)) {
747
            set_DSPControl_overflow_flag(1, 22, env);
748
        }
749
        return a << s;
750
    }
751
}
752

    
753

    
754
static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
755
                                        CPUMIPSState *env)
756
{
757
    uint32_t discard;
758

    
759
    if (s == 0) {
760
        return a;
761
    } else {
762
        discard = (int32_t)a >> (31 - (s - 1));
763

    
764
        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
765
            set_DSPControl_overflow_flag(1, 22, env);
766
        }
767
        return a << s;
768
    }
769
}
770

    
771
static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
772
                                            CPUMIPSState *env)
773
{
774
    uint8_t  sign;
775
    uint16_t discard;
776

    
777
    if (s == 0) {
778
        return a;
779
    } else {
780
        sign = (a >> 15) & 0x01;
781
        if (sign != 0) {
782
            discard = (((0x01 << (16 - s)) - 1) << s) |
783
                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
784
        } else {
785
            discard = a >> (14 - (s - 1));
786
        }
787

    
788
        if ((discard != 0x0000) && (discard != 0xFFFF)) {
789
            set_DSPControl_overflow_flag(1, 22, env);
790
            return (sign == 0) ? 0x7FFF : 0x8000;
791
        } else {
792
            return a << s;
793
        }
794
    }
795
}
796

    
797
static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s,
798
                                            CPUMIPSState *env)
799
{
800
    uint8_t  sign;
801
    uint32_t discard;
802

    
803
    if (s == 0) {
804
        return a;
805
    } else {
806
        sign = (a >> 31) & 0x01;
807
        if (sign != 0) {
808
            discard = (((0x01 << (32 - s)) - 1) << s) |
809
                      ((a >> (30 - (s - 1))) & ((0x01 << s) - 1));
810
        } else {
811
            discard = a >> (30 - (s - 1));
812
        }
813

    
814
        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
815
            set_DSPControl_overflow_flag(1, 22, env);
816
            return (sign == 0) ? 0x7FFFFFFF : 0x80000000;
817
        } else {
818
            return a << s;
819
        }
820
    }
821
}
822

    
823
static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s)
824
{
825
    uint32_t temp;
826

    
827
    if (s == 0) {
828
        temp = (uint32_t)a << 1;
829
    } else {
830
        temp = (int32_t)(int8_t)a >> (s - 1);
831
    }
832

    
833
    return (temp + 1) >> 1;
834
}
835

    
836
static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
837
{
838
    uint32_t temp;
839

    
840
    if (s == 0) {
841
        temp = (uint32_t)a << 1;
842
    } else {
843
        temp = (int32_t)(int16_t)a >> (s - 1);
844
    }
845

    
846
    return (temp + 1) >> 1;
847
}
848

    
849
static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
850
{
851
    int64_t temp;
852

    
853
    if (s == 0) {
854
        temp = (uint64_t)a << 1;
855
    } else {
856
        temp = (int64_t)(int32_t)a >> (s - 1);
857
    }
858
    temp += 1;
859

    
860
    return (temp >> 1) & 0xFFFFFFFFull;
861
}
862

    
863
static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
864
{
865
    int16_t  temp;
866

    
867
    temp = a - b;
868
    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
869
        set_DSPControl_overflow_flag(1, 20, env);
870
    }
871

    
872
    return temp;
873
}
874

    
875
static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
876
                                         CPUMIPSState *env)
877
{
878
    int16_t  temp;
879

    
880
    temp = a - b;
881
    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
882
        if (a > 0) {
883
            temp = 0x7FFF;
884
        } else {
885
            temp = 0x8000;
886
        }
887
        set_DSPControl_overflow_flag(1, 20, env);
888
    }
889

    
890
    return temp;
891
}
892

    
893
static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
894
                                         CPUMIPSState *env)
895
{
896
    int32_t  temp;
897

    
898
    temp = a - b;
899
    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
900
        if (a > 0) {
901
            temp = 0x7FFFFFFF;
902
        } else {
903
            temp = 0x80000000;
904
        }
905
        set_DSPControl_overflow_flag(1, 20, env);
906
    }
907

    
908
    return temp & 0xFFFFFFFFull;
909
}
910

    
911
static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
912
{
913
    int32_t  temp;
914

    
915
    temp = (int32_t)a - (int32_t)b;
916

    
917
    return (temp >> 1) & 0x0000FFFF;
918
}
919

    
920
static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
921
{
922
    int32_t  temp;
923

    
924
    temp = (int32_t)a - (int32_t)b;
925
    temp += 1;
926

    
927
    return (temp >> 1) & 0x0000FFFF;
928
}
929

    
930
static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
931
{
932
    int64_t  temp;
933

    
934
    temp = (int64_t)a - (int64_t)b;
935

    
936
    return (temp >> 1) & 0xFFFFFFFFull;
937
}
938

    
939
static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
940
{
941
    int64_t  temp;
942

    
943
    temp = (int64_t)a - (int64_t)b;
944
    temp += 1;
945

    
946
    return (temp >> 1) & 0xFFFFFFFFull;
947
}
948

    
949
static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b,
950
                                           CPUMIPSState *env)
951
{
952
    uint8_t  temp16;
953
    uint32_t temp;
954

    
955
    temp = (uint32_t)a - (uint32_t)b;
956
    temp16 = (temp >> 16) & 0x01;
957
    if (temp16 == 1) {
958
        set_DSPControl_overflow_flag(1, 20, env);
959
    }
960
    return temp & 0x0000FFFF;
961
}
962

    
963
static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b,
964
                                                  CPUMIPSState *env)
965
{
966
    uint8_t  temp16;
967
    uint32_t temp;
968

    
969
    temp   = (uint32_t)a - (uint32_t)b;
970
    temp16 = (temp >> 16) & 0x01;
971

    
972
    if (temp16 == 1) {
973
        temp = 0x0000;
974
        set_DSPControl_overflow_flag(1, 20, env);
975
    }
976

    
977
    return temp & 0x0000FFFF;
978
}
979

    
980
static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
981
{
982
    uint8_t  temp8;
983
    uint16_t temp;
984

    
985
    temp = (uint16_t)a - (uint16_t)b;
986
    temp8 = (temp >> 8) & 0x01;
987
    if (temp8 == 1) {
988
        set_DSPControl_overflow_flag(1, 20, env);
989
    }
990

    
991
    return temp & 0x00FF;
992
}
993

    
994
static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
995
{
996
    uint8_t  temp8;
997
    uint16_t temp;
998

    
999
    temp = (uint16_t)a - (uint16_t)b;
1000
    temp8 = (temp >> 8) & 0x01;
1001
    if (temp8 == 1) {
1002
        temp = 0x00;
1003
        set_DSPControl_overflow_flag(1, 20, env);
1004
    }
1005

    
1006
    return temp & 0x00FF;
1007
}
1008

    
1009
static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
1010
{
1011
    int32_t temp;
1012

    
1013
    temp = a - b;
1014
    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
1015
        set_DSPControl_overflow_flag(1, 20, env);
1016
    }
1017

    
1018
    return temp;
1019
}
1020

    
1021
static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
1022
{
1023
    int32_t temp;
1024

    
1025
    temp = a + b;
1026

    
1027
    if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) {
1028
        set_DSPControl_overflow_flag(1, 20, env);
1029
    }
1030

    
1031
    return temp;
1032
}
1033

    
1034
static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b)
1035
{
1036
    return a == b;
1037
}
1038

    
1039
static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b)
1040
{
1041
    return a <= b;
1042
}
1043

    
1044
static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b)
1045
{
1046
    return a < b;
1047
}
1048

    
1049
static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b)
1050
{
1051
    return a == b;
1052
}
1053

    
1054
static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b)
1055
{
1056
    return a <= b;
1057
}
1058

    
1059
static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
1060
{
1061
    return a < b;
1062
}
1063
/*** MIPS DSP internal functions end ***/
1064

    
1065
#define MIPSDSP_LHI 0xFFFFFFFF00000000ull
1066
#define MIPSDSP_LLO 0x00000000FFFFFFFFull
1067
#define MIPSDSP_HI  0xFFFF0000
1068
#define MIPSDSP_LO  0x0000FFFF
1069
#define MIPSDSP_Q3  0xFF000000
1070
#define MIPSDSP_Q2  0x00FF0000
1071
#define MIPSDSP_Q1  0x0000FF00
1072
#define MIPSDSP_Q0  0x000000FF
1073

    
1074
#define MIPSDSP_SPLIT32_8(num, a, b, c, d)  \
1075
    do {                                    \
1076
        a = (num >> 24) & MIPSDSP_Q0;       \
1077
        b = (num >> 16) & MIPSDSP_Q0;       \
1078
        c = (num >> 8) & MIPSDSP_Q0;        \
1079
        d = num & MIPSDSP_Q0;               \
1080
    } while (0)
1081

    
1082
#define MIPSDSP_SPLIT32_16(num, a, b)       \
1083
    do {                                    \
1084
        a = (num >> 16) & MIPSDSP_LO;       \
1085
        b = num & MIPSDSP_LO;               \
1086
    } while (0)
1087

    
1088
#define MIPSDSP_RETURN32(a)             ((target_long)(int32_t)a)
1089
#define MIPSDSP_RETURN32_8(a, b, c, d)  ((target_long)(int32_t) \
1090
                                         (((uint32_t)a << 24) | \
1091
                                         (((uint32_t)b << 16) | \
1092
                                         (((uint32_t)c << 8) |  \
1093
                                          ((uint32_t)d & 0xFF)))))
1094
#define MIPSDSP_RETURN32_16(a, b)       ((target_long)(int32_t) \
1095
                                         (((uint32_t)a << 16) | \
1096
                                          ((uint32_t)b & 0xFFFF)))
1097

    
1098
#ifdef TARGET_MIPS64
1099
#define MIPSDSP_SPLIT64_16(num, a, b, c, d)  \
1100
    do {                                     \
1101
        a = (num >> 48) & MIPSDSP_LO;        \
1102
        b = (num >> 32) & MIPSDSP_LO;        \
1103
        c = (num >> 16) & MIPSDSP_LO;        \
1104
        d = num & MIPSDSP_LO;                \
1105
    } while (0)
1106

    
1107
#define MIPSDSP_SPLIT64_32(num, a, b)       \
1108
    do {                                    \
1109
        a = (num >> 32) & MIPSDSP_LLO;      \
1110
        b = num & MIPSDSP_LLO;              \
1111
    } while (0)
1112

    
1113
#define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
1114
                                         ((uint64_t)b << 32) | \
1115
                                         ((uint64_t)c << 16) | \
1116
                                         (uint64_t)d)
1117
#define MIPSDSP_RETURN64_32(a, b)       (((uint64_t)a << 32) | (uint64_t)b)
1118
#endif
1119

    
1120
/** DSP Arithmetic Sub-class insns **/
1121
#define ARITH_PH(name, func)                                      \
1122
target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt) \
1123
{                                                                 \
1124
    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
1125
                                                                  \
1126
    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
1127
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
1128
                                                                  \
1129
    temph = mipsdsp_##func(rsh, rth);                             \
1130
    templ = mipsdsp_##func(rsl, rtl);                             \
1131
                                                                  \
1132
    return MIPSDSP_RETURN32_16(temph, templ);                     \
1133
}
1134

    
1135
#define ARITH_PH_ENV(name, func)                                  \
1136
target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt, \
1137
                                CPUMIPSState *env)                \
1138
{                                                                 \
1139
    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
1140
                                                                  \
1141
    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
1142
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
1143
                                                                  \
1144
    temph = mipsdsp_##func(rsh, rth, env);                        \
1145
    templ = mipsdsp_##func(rsl, rtl, env);                        \
1146
                                                                  \
1147
    return MIPSDSP_RETURN32_16(temph, templ);                     \
1148
}
1149

    
1150

    
1151
ARITH_PH_ENV(addq, add_i16);
1152
ARITH_PH_ENV(addq_s, sat_add_i16);
1153
ARITH_PH_ENV(addu, add_u16);
1154
ARITH_PH_ENV(addu_s, sat_add_u16);
1155

    
1156
ARITH_PH(addqh, rshift1_add_q16);
1157
ARITH_PH(addqh_r, rrshift1_add_q16);
1158

    
1159
ARITH_PH_ENV(subq, sub_i16);
1160
ARITH_PH_ENV(subq_s, sat16_sub);
1161
ARITH_PH_ENV(subu, sub_u16_u16);
1162
ARITH_PH_ENV(subu_s, satu16_sub_u16_u16);
1163

    
1164
ARITH_PH(subqh, rshift1_sub_q16);
1165
ARITH_PH(subqh_r, rrshift1_sub_q16);
1166

    
1167
#undef ARITH_PH
1168
#undef ARITH_PH_ENV
1169

    
1170
#ifdef TARGET_MIPS64
1171
#define ARITH_QH_ENV(name, func) \
1172
target_ulong helper_##name##_qh(target_ulong rs, target_ulong rt, \
1173
                                CPUMIPSState *env)           \
1174
{                                                            \
1175
    uint16_t rs3, rs2, rs1, rs0;                             \
1176
    uint16_t rt3, rt2, rt1, rt0;                             \
1177
    uint16_t tempD, tempC, tempB, tempA;                     \
1178
                                                             \
1179
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);              \
1180
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);              \
1181
                                                             \
1182
    tempD = mipsdsp_##func(rs3, rt3, env);                   \
1183
    tempC = mipsdsp_##func(rs2, rt2, env);                   \
1184
    tempB = mipsdsp_##func(rs1, rt1, env);                   \
1185
    tempA = mipsdsp_##func(rs0, rt0, env);                   \
1186
                                                             \
1187
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1188
}
1189

    
1190
ARITH_QH_ENV(addq, add_i16);
1191
ARITH_QH_ENV(addq_s, sat_add_i16);
1192
ARITH_QH_ENV(addu, add_u16);
1193
ARITH_QH_ENV(addu_s, sat_add_u16);
1194

    
1195
ARITH_QH_ENV(subq, sub_i16);
1196
ARITH_QH_ENV(subq_s, sat16_sub);
1197
ARITH_QH_ENV(subu, sub_u16_u16);
1198
ARITH_QH_ENV(subu_s, satu16_sub_u16_u16);
1199

    
1200
#undef ARITH_QH_ENV
1201

    
1202
#endif
1203

    
1204
#define ARITH_W(name, func) \
1205
target_ulong helper_##name##_w(target_ulong rs, target_ulong rt) \
1206
{                                                                \
1207
    uint32_t rd;                                                 \
1208
    rd = mipsdsp_##func(rs, rt);                                 \
1209
    return MIPSDSP_RETURN32(rd);                                 \
1210
}
1211

    
1212
#define ARITH_W_ENV(name, func) \
1213
target_ulong helper_##name##_w(target_ulong rs, target_ulong rt, \
1214
                               CPUMIPSState *env)                \
1215
{                                                                \
1216
    uint32_t rd;                                                 \
1217
    rd = mipsdsp_##func(rs, rt, env);                            \
1218
    return MIPSDSP_RETURN32(rd);                                 \
1219
}
1220

    
1221
ARITH_W_ENV(addq_s, sat_add_i32);
1222

    
1223
ARITH_W(addqh, rshift1_add_q32);
1224
ARITH_W(addqh_r, rrshift1_add_q32);
1225

    
1226
ARITH_W_ENV(subq_s, sat32_sub);
1227

    
1228
ARITH_W(subqh, rshift1_sub_q32);
1229
ARITH_W(subqh_r, rrshift1_sub_q32);
1230

    
1231
#undef ARITH_W
1232
#undef ARITH_W_ENV
1233

    
1234
target_ulong helper_absq_s_w(target_ulong rt, CPUMIPSState *env)
1235
{
1236
    uint32_t rd;
1237

    
1238
    rd = mipsdsp_sat_abs32(rt, env);
1239

    
1240
    return (target_ulong)rd;
1241
}
1242

    
1243

    
1244
#if defined(TARGET_MIPS64)
1245

    
1246
#define ARITH_PW_ENV(name, func) \
1247
target_ulong helper_##name##_pw(target_ulong rs, target_ulong rt, \
1248
                                CPUMIPSState *env)                \
1249
{                                                                 \
1250
    uint32_t rs1, rs0;                                            \
1251
    uint32_t rt1, rt0;                                            \
1252
    uint32_t tempB, tempA;                                        \
1253
                                                                  \
1254
    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
1255
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
1256
                                                                  \
1257
    tempB = mipsdsp_##func(rs1, rt1, env);                        \
1258
    tempA = mipsdsp_##func(rs0, rt0, env);                        \
1259
                                                                  \
1260
    return MIPSDSP_RETURN64_32(tempB, tempA);                     \
1261
}
1262

    
1263
ARITH_PW_ENV(addq, add_i32);
1264
ARITH_PW_ENV(addq_s, sat_add_i32);
1265
ARITH_PW_ENV(subq, sub32);
1266
ARITH_PW_ENV(subq_s, sat32_sub);
1267

    
1268
#undef ARITH_PW_ENV
1269

    
1270
#endif
1271

    
1272
#define ARITH_QB(name, func) \
1273
target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
1274
{                                                                 \
1275
    uint8_t  rs0, rs1, rs2, rs3;                                  \
1276
    uint8_t  rt0, rt1, rt2, rt3;                                  \
1277
    uint8_t  temp0, temp1, temp2, temp3;                          \
1278
                                                                  \
1279
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
1280
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
1281
                                                                  \
1282
    temp0 = mipsdsp_##func(rs0, rt0);                             \
1283
    temp1 = mipsdsp_##func(rs1, rt1);                             \
1284
    temp2 = mipsdsp_##func(rs2, rt2);                             \
1285
    temp3 = mipsdsp_##func(rs3, rt3);                             \
1286
                                                                  \
1287
    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);        \
1288
}
1289

    
1290
#define ARITH_QB_ENV(name, func) \
1291
target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt, \
1292
                                CPUMIPSState *env)          \
1293
{                                                           \
1294
    uint8_t  rs0, rs1, rs2, rs3;                            \
1295
    uint8_t  rt0, rt1, rt2, rt3;                            \
1296
    uint8_t  temp0, temp1, temp2, temp3;                    \
1297
                                                            \
1298
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);              \
1299
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);              \
1300
                                                            \
1301
    temp0 = mipsdsp_##func(rs0, rt0, env);                  \
1302
    temp1 = mipsdsp_##func(rs1, rt1, env);                  \
1303
    temp2 = mipsdsp_##func(rs2, rt2, env);                  \
1304
    temp3 = mipsdsp_##func(rs3, rt3, env);                  \
1305
                                                            \
1306
    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);  \
1307
}
1308

    
1309
ARITH_QB(adduh, rshift1_add_u8);
1310
ARITH_QB(adduh_r, rrshift1_add_u8);
1311

    
1312
ARITH_QB_ENV(addu, add_u8);
1313
ARITH_QB_ENV(addu_s, sat_add_u8);
1314

    
1315
#undef ADDU_QB
1316
#undef ADDU_QB_ENV
1317

    
1318
#if defined(TARGET_MIPS64)
1319
#define ARITH_OB(name, func) \
1320
target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt) \
1321
{                                                                 \
1322
    int i;                                                        \
1323
    uint8_t rs_t[8], rt_t[8];                                     \
1324
    uint8_t temp[8];                                              \
1325
    uint64_t result;                                              \
1326
                                                                  \
1327
    result = 0;                                                   \
1328
                                                                  \
1329
    for (i = 0; i < 8; i++) {                                     \
1330
        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;                   \
1331
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                   \
1332
        temp[i] = mipsdsp_##func(rs_t[i], rt_t[i]);               \
1333
        result |= (uint64_t)temp[i] << (8 * i);                   \
1334
    }                                                             \
1335
                                                                  \
1336
    return result;                                                \
1337
}
1338

    
1339
#define ARITH_OB_ENV(name, func) \
1340
target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt, \
1341
                                CPUMIPSState *env)                \
1342
{                                                                 \
1343
    int i;                                                        \
1344
    uint8_t rs_t[8], rt_t[8];                                     \
1345
    uint8_t temp[8];                                              \
1346
    uint64_t result;                                              \
1347
                                                                  \
1348
    result = 0;                                                   \
1349
                                                                  \
1350
    for (i = 0; i < 8; i++) {                                     \
1351
        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;                   \
1352
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                   \
1353
        temp[i] = mipsdsp_##func(rs_t[i], rt_t[i], env);          \
1354
        result |= (uint64_t)temp[i] << (8 * i);                   \
1355
    }                                                             \
1356
                                                                  \
1357
    return result;                                                \
1358
}
1359

    
1360
ARITH_OB_ENV(addu, add_u8);
1361
ARITH_OB_ENV(addu_s, sat_add_u8);
1362

    
1363
ARITH_OB(adduh, rshift1_add_u8);
1364
ARITH_OB(adduh_r, rrshift1_add_u8);
1365

    
1366
ARITH_OB_ENV(subu, sub_u8);
1367
ARITH_OB_ENV(subu_s, satu8_sub);
1368

    
1369
ARITH_OB(subuh, rshift1_sub_u8);
1370
ARITH_OB(subuh_r, rrshift1_sub_u8);
1371

    
1372
#undef ARITH_OB
1373
#undef ARITH_OB_ENV
1374

    
1375
#endif
1376

    
1377
#define SUBU_QB(name, func) \
1378
target_ulong helper_##name##_qb(target_ulong rs,               \
1379
                                target_ulong rt,               \
1380
                                CPUMIPSState *env)             \
1381
{                                                              \
1382
    uint8_t rs3, rs2, rs1, rs0;                                \
1383
    uint8_t rt3, rt2, rt1, rt0;                                \
1384
    uint8_t tempD, tempC, tempB, tempA;                        \
1385
                                                               \
1386
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                 \
1387
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                 \
1388
                                                               \
1389
    tempD = mipsdsp_##func(rs3, rt3, env);                     \
1390
    tempC = mipsdsp_##func(rs2, rt2, env);                     \
1391
    tempB = mipsdsp_##func(rs1, rt1, env);                     \
1392
    tempA = mipsdsp_##func(rs0, rt0, env);                     \
1393
                                                               \
1394
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);     \
1395
}
1396

    
1397
SUBU_QB(subu, sub_u8);
1398
SUBU_QB(subu_s, satu8_sub);
1399

    
1400
#undef SUBU_QB
1401

    
1402
#define SUBUH_QB(name, var) \
1403
target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
1404
{                                                                 \
1405
    uint8_t rs3, rs2, rs1, rs0;                                   \
1406
    uint8_t rt3, rt2, rt1, rt0;                                   \
1407
    uint8_t tempD, tempC, tempB, tempA;                           \
1408
                                                                  \
1409
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
1410
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
1411
                                                                  \
1412
    tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1;           \
1413
    tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1;           \
1414
    tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1;           \
1415
    tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1;           \
1416
                                                                  \
1417
    return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |    \
1418
        ((uint32_t)tempB << 8) | ((uint32_t)tempA);               \
1419
}
1420

    
1421
SUBUH_QB(subuh, 0);
1422
SUBUH_QB(subuh_r, 1);
1423

    
1424
#undef SUBUH_QB
1425

    
1426
target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1427
{
1428
    uint64_t temp, tempRs, tempRt;
1429
    int32_t flag;
1430

    
1431
    tempRs = (uint64_t)rs & MIPSDSP_LLO;
1432
    tempRt = (uint64_t)rt & MIPSDSP_LLO;
1433

    
1434
    temp = tempRs + tempRt;
1435
    flag = (temp & 0x0100000000ull) >> 32;
1436
    set_DSPControl_carryflag(flag, env);
1437

    
1438
    return (target_long)(int32_t)(temp & MIPSDSP_LLO);
1439
}
1440

    
1441
target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
1442
{
1443
    uint32_t rd;
1444
    int32_t temp32, temp31;
1445
    int64_t tempL;
1446

    
1447
    tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt +
1448
        get_DSPControl_carryflag(env);
1449
    temp31 = (tempL >> 31) & 0x01;
1450
    temp32 = (tempL >> 32) & 0x01;
1451

    
1452
    if (temp31 != temp32) {
1453
        set_DSPControl_overflow_flag(1, 20, env);
1454
    }
1455

    
1456
    rd = tempL & MIPSDSP_LLO;
1457

    
1458
    return (target_long)(int32_t)rd;
1459
}
1460

    
1461
target_ulong helper_modsub(target_ulong rs, target_ulong rt)
1462
{
1463
    int32_t decr;
1464
    uint16_t lastindex;
1465
    target_ulong rd;
1466

    
1467
    decr = rt & MIPSDSP_Q0;
1468
    lastindex = (rt >> 8) & MIPSDSP_LO;
1469

    
1470
    if ((rs & MIPSDSP_LLO) == 0x00000000) {
1471
        rd = (target_ulong)lastindex;
1472
    } else {
1473
        rd = rs - decr;
1474
    }
1475

    
1476
    return rd;
1477
}
1478

    
1479
target_ulong helper_raddu_w_qb(target_ulong rs)
1480
{
1481
    uint8_t  rs3, rs2, rs1, rs0;
1482
    uint16_t temp;
1483

    
1484
    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);
1485

    
1486
    temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0;
1487

    
1488
    return (target_ulong)temp;
1489
}
1490

    
1491
#if defined(TARGET_MIPS64)
1492
target_ulong helper_raddu_l_ob(target_ulong rs)
1493
{
1494
    int i;
1495
    uint16_t rs_t[8];
1496
    uint64_t temp;
1497

    
1498
    temp = 0;
1499

    
1500
    for (i = 0; i < 8; i++) {
1501
        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
1502
        temp += (uint64_t)rs_t[i];
1503
    }
1504

    
1505
    return temp;
1506
}
1507
#endif
1508

    
1509
target_ulong helper_absq_s_qb(target_ulong rt, CPUMIPSState *env)
1510
{
1511
    uint8_t tempD, tempC, tempB, tempA;
1512

    
1513
    MIPSDSP_SPLIT32_8(rt, tempD, tempC, tempB, tempA);
1514

    
1515
    tempD = mipsdsp_sat_abs8(tempD, env);
1516
    tempC = mipsdsp_sat_abs8(tempC, env);
1517
    tempB = mipsdsp_sat_abs8(tempB, env);
1518
    tempA = mipsdsp_sat_abs8(tempA, env);
1519

    
1520
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
1521
}
1522

    
1523
target_ulong helper_absq_s_ph(target_ulong rt, CPUMIPSState *env)
1524
{
1525
    uint16_t tempB, tempA;
1526

    
1527
    MIPSDSP_SPLIT32_16(rt, tempB, tempA);
1528

    
1529
    tempB = mipsdsp_sat_abs16 (tempB, env);
1530
    tempA = mipsdsp_sat_abs16 (tempA, env);
1531

    
1532
    return MIPSDSP_RETURN32_16(tempB, tempA);
1533
}
1534

    
1535
#if defined(TARGET_MIPS64)
1536
target_ulong helper_absq_s_ob(target_ulong rt, CPUMIPSState *env)
1537
{
1538
    int i;
1539
    int8_t temp[8];
1540
    uint64_t result;
1541

    
1542
    for (i = 0; i < 8; i++) {
1543
        temp[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
1544
        temp[i] = mipsdsp_sat_abs8(temp[i], env);
1545
    }
1546

    
1547
    for (i = 0; i < 8; i++) {
1548
        result = (uint64_t)(uint8_t)temp[i] << (8 * i);
1549
    }
1550

    
1551
    return result;
1552
}
1553

    
1554
target_ulong helper_absq_s_qh(target_ulong rt, CPUMIPSState *env)
1555
{
1556
    int16_t tempD, tempC, tempB, tempA;
1557

    
1558
    MIPSDSP_SPLIT64_16(rt, tempD, tempC, tempB, tempA);
1559

    
1560
    tempD = mipsdsp_sat_abs16(tempD, env);
1561
    tempC = mipsdsp_sat_abs16(tempC, env);
1562
    tempB = mipsdsp_sat_abs16(tempB, env);
1563
    tempA = mipsdsp_sat_abs16(tempA, env);
1564

    
1565
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1566
}
1567

    
1568
target_ulong helper_absq_s_pw(target_ulong rt, CPUMIPSState *env)
1569
{
1570
    int32_t tempB, tempA;
1571

    
1572
    MIPSDSP_SPLIT64_32(rt, tempB, tempA);
1573

    
1574
    tempB = mipsdsp_sat_abs32(tempB, env);
1575
    tempA = mipsdsp_sat_abs32(tempA, env);
1576

    
1577
    return MIPSDSP_RETURN64_32(tempB, tempA);
1578
}
1579
#endif
1580

    
1581
#define PRECR_QB_PH(name, a, b)\
1582
target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \
1583
{                                                                    \
1584
    uint8_t tempD, tempC, tempB, tempA;                              \
1585
                                                                     \
1586
    tempD = (rs >> a) & MIPSDSP_Q0;                                  \
1587
    tempC = (rs >> b) & MIPSDSP_Q0;                                  \
1588
    tempB = (rt >> a) & MIPSDSP_Q0;                                  \
1589
    tempA = (rt >> b) & MIPSDSP_Q0;                                  \
1590
                                                                     \
1591
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);           \
1592
}
1593

    
1594
PRECR_QB_PH(precr, 16, 0);
1595
PRECR_QB_PH(precrq, 24, 8);
1596

    
1597
#undef PRECR_QB_OH
1598

    
1599
target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
1600
                                   target_ulong rt)
1601
{
1602
    uint16_t tempB, tempA;
1603

    
1604
    tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
1605
    tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
1606

    
1607
    return MIPSDSP_RETURN32_16(tempB, tempA);
1608
}
1609

    
1610
target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
1611
                                     target_ulong rs, target_ulong rt)
1612
{
1613
    uint64_t tempB, tempA;
1614

    
1615
    /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */
1616
    if (sa == 0) {
1617
        tempB = (rt & MIPSDSP_LO) << 1;
1618
        tempA = (rs & MIPSDSP_LO) << 1;
1619
    } else {
1620
        tempB = ((int32_t)rt >> (sa - 1)) + 1;
1621
        tempA = ((int32_t)rs >> (sa - 1)) + 1;
1622
    }
1623
    rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
1624

    
1625
    return (target_long)(int32_t)rt;
1626
}
1627

    
1628
target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
1629
{
1630
    uint16_t tempB, tempA;
1631

    
1632
    tempB = (rs & MIPSDSP_HI) >> 16;
1633
    tempA = (rt & MIPSDSP_HI) >> 16;
1634

    
1635
    return MIPSDSP_RETURN32_16(tempB, tempA);
1636
}
1637

    
1638
target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt,
1639
                                   CPUMIPSState *env)
1640
{
1641
    uint16_t tempB, tempA;
1642

    
1643
    tempB = mipsdsp_trunc16_sat16_round(rs, env);
1644
    tempA = mipsdsp_trunc16_sat16_round(rt, env);
1645

    
1646
    return MIPSDSP_RETURN32_16(tempB, tempA);
1647
}
1648

    
1649
#if defined(TARGET_MIPS64)
1650
target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
1651
{
1652
    uint8_t rs6, rs4, rs2, rs0;
1653
    uint8_t rt6, rt4, rt2, rt0;
1654
    uint64_t temp;
1655

    
1656
    rs6 = (rs >> 48) & MIPSDSP_Q0;
1657
    rs4 = (rs >> 32) & MIPSDSP_Q0;
1658
    rs2 = (rs >> 16) & MIPSDSP_Q0;
1659
    rs0 = rs & MIPSDSP_Q0;
1660
    rt6 = (rt >> 48) & MIPSDSP_Q0;
1661
    rt4 = (rt >> 32) & MIPSDSP_Q0;
1662
    rt2 = (rt >> 16) & MIPSDSP_Q0;
1663
    rt0 = rt & MIPSDSP_Q0;
1664

    
1665
    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1666
           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1667
           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1668
           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1669

    
1670
    return temp;
1671
}
1672

    
1673
#define PRECR_QH_PW(name, var) \
1674
target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \
1675
                                    uint32_t sa)                      \
1676
{                                                                     \
1677
    uint16_t rs3, rs2, rs1, rs0;                                      \
1678
    uint16_t rt3, rt2, rt1, rt0;                                      \
1679
    uint16_t tempD, tempC, tempB, tempA;                              \
1680
                                                                      \
1681
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                       \
1682
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                       \
1683
                                                                      \
1684
    /* When sa = 0, we use rt2, rt0, rs2, rs0;                        \
1685
     * when sa != 0, we use rt3, rt1, rs3, rs1. */                    \
1686
    if (sa == 0) {                                                    \
1687
        tempD = rt2 << var;                                           \
1688
        tempC = rt0 << var;                                           \
1689
        tempB = rs2 << var;                                           \
1690
        tempA = rs0 << var;                                           \
1691
    } else {                                                          \
1692
        tempD = (((int16_t)rt3 >> sa) + var) >> var;                  \
1693
        tempC = (((int16_t)rt1 >> sa) + var) >> var;                  \
1694
        tempB = (((int16_t)rs3 >> sa) + var) >> var;                  \
1695
        tempA = (((int16_t)rs1 >> sa) + var) >> var;                  \
1696
    }                                                                 \
1697
                                                                      \
1698
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);           \
1699
}
1700

    
1701
PRECR_QH_PW(sra, 0);
1702
PRECR_QH_PW(sra_r, 1);
1703

    
1704
#undef PRECR_QH_PW
1705

    
1706
target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
1707
{
1708
    uint8_t rs6, rs4, rs2, rs0;
1709
    uint8_t rt6, rt4, rt2, rt0;
1710
    uint64_t temp;
1711

    
1712
    rs6 = (rs >> 56) & MIPSDSP_Q0;
1713
    rs4 = (rs >> 40) & MIPSDSP_Q0;
1714
    rs2 = (rs >> 24) & MIPSDSP_Q0;
1715
    rs0 = (rs >> 8) & MIPSDSP_Q0;
1716
    rt6 = (rt >> 56) & MIPSDSP_Q0;
1717
    rt4 = (rt >> 40) & MIPSDSP_Q0;
1718
    rt2 = (rt >> 24) & MIPSDSP_Q0;
1719
    rt0 = (rt >> 8) & MIPSDSP_Q0;
1720

    
1721
    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
1722
           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
1723
           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
1724
           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
1725

    
1726
    return temp;
1727
}
1728

    
1729
target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
1730
{
1731
    uint16_t tempD, tempC, tempB, tempA;
1732

    
1733
    tempD = (rs >> 48) & MIPSDSP_LO;
1734
    tempC = (rs >> 16) & MIPSDSP_LO;
1735
    tempB = (rt >> 48) & MIPSDSP_LO;
1736
    tempA = (rt >> 16) & MIPSDSP_LO;
1737

    
1738
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1739
}
1740

    
1741
target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt,
1742
                                    CPUMIPSState *env)
1743
{
1744
    uint32_t rs2, rs0;
1745
    uint32_t rt2, rt0;
1746
    uint16_t tempD, tempC, tempB, tempA;
1747

    
1748
    rs2 = (rs >> 32) & MIPSDSP_LLO;
1749
    rs0 = rs & MIPSDSP_LLO;
1750
    rt2 = (rt >> 32) & MIPSDSP_LLO;
1751
    rt0 = rt & MIPSDSP_LLO;
1752

    
1753
    tempD = mipsdsp_trunc16_sat16_round(rs2, env);
1754
    tempC = mipsdsp_trunc16_sat16_round(rs0, env);
1755
    tempB = mipsdsp_trunc16_sat16_round(rt2, env);
1756
    tempA = mipsdsp_trunc16_sat16_round(rt0, env);
1757

    
1758
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
1759
}
1760

    
1761
target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
1762
{
1763
    uint32_t tempB, tempA;
1764

    
1765
    tempB = (rs >> 32) & MIPSDSP_LLO;
1766
    tempA = (rt >> 32) & MIPSDSP_LLO;
1767

    
1768
    return MIPSDSP_RETURN64_32(tempB, tempA);
1769
}
1770
#endif
1771

    
1772
target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt,
1773
                                    CPUMIPSState *env)
1774
{
1775
    uint8_t  tempD, tempC, tempB, tempA;
1776
    uint16_t rsh, rsl, rth, rtl;
1777

    
1778
    rsh = (rs & MIPSDSP_HI) >> 16;
1779
    rsl =  rs & MIPSDSP_LO;
1780
    rth = (rt & MIPSDSP_HI) >> 16;
1781
    rtl =  rt & MIPSDSP_LO;
1782

    
1783
    tempD = mipsdsp_sat8_reduce_precision(rsh, env);
1784
    tempC = mipsdsp_sat8_reduce_precision(rsl, env);
1785
    tempB = mipsdsp_sat8_reduce_precision(rth, env);
1786
    tempA = mipsdsp_sat8_reduce_precision(rtl, env);
1787

    
1788
    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
1789
}
1790

    
1791
#if defined(TARGET_MIPS64)
1792
target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt,
1793
                                    CPUMIPSState *env)
1794
{
1795
    int i;
1796
    uint16_t rs3, rs2, rs1, rs0;
1797
    uint16_t rt3, rt2, rt1, rt0;
1798
    uint8_t temp[8];
1799
    uint64_t result;
1800

    
1801
    result = 0;
1802

    
1803
    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
1804
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
1805

    
1806
    temp[7] = mipsdsp_sat8_reduce_precision(rs3, env);
1807
    temp[6] = mipsdsp_sat8_reduce_precision(rs2, env);
1808
    temp[5] = mipsdsp_sat8_reduce_precision(rs1, env);
1809
    temp[4] = mipsdsp_sat8_reduce_precision(rs0, env);
1810
    temp[3] = mipsdsp_sat8_reduce_precision(rt3, env);
1811
    temp[2] = mipsdsp_sat8_reduce_precision(rt2, env);
1812
    temp[1] = mipsdsp_sat8_reduce_precision(rt1, env);
1813
    temp[0] = mipsdsp_sat8_reduce_precision(rt0, env);
1814

    
1815
    for (i = 0; i < 8; i++) {
1816
        result |= (uint64_t)temp[i] << (8 * i);
1817
    }
1818

    
1819
    return result;
1820
}
1821

    
1822
#define PRECEQ_PW(name, a, b) \
1823
target_ulong helper_preceq_pw_##name(target_ulong rt) \
1824
{                                                       \
1825
    uint16_t tempB, tempA;                              \
1826
    uint32_t tempBI, tempAI;                            \
1827
                                                        \
1828
    tempB = (rt >> a) & MIPSDSP_LO;                     \
1829
    tempA = (rt >> b) & MIPSDSP_LO;                     \
1830
                                                        \
1831
    tempBI = (uint32_t)tempB << 16;                     \
1832
    tempAI = (uint32_t)tempA << 16;                     \
1833
                                                        \
1834
    return MIPSDSP_RETURN64_32(tempBI, tempAI);         \
1835
}
1836

    
1837
PRECEQ_PW(qhl, 48, 32);
1838
PRECEQ_PW(qhr, 16, 0);
1839
PRECEQ_PW(qhla, 48, 16);
1840
PRECEQ_PW(qhra, 32, 0);
1841

    
1842
#undef PRECEQ_PW
1843

    
1844
#endif
1845

    
1846
#define PRECEQU_PH(name, a, b) \
1847
target_ulong helper_precequ_ph_##name(target_ulong rt) \
1848
{                                                        \
1849
    uint16_t tempB, tempA;                               \
1850
                                                         \
1851
    tempB = (rt >> a) & MIPSDSP_Q0;                      \
1852
    tempA = (rt >> b) & MIPSDSP_Q0;                      \
1853
                                                         \
1854
    tempB = tempB << 7;                                  \
1855
    tempA = tempA << 7;                                  \
1856
                                                         \
1857
    return MIPSDSP_RETURN32_16(tempB, tempA);            \
1858
}
1859

    
1860
PRECEQU_PH(qbl, 24, 16);
1861
PRECEQU_PH(qbr, 8, 0);
1862
PRECEQU_PH(qbla, 24, 8);
1863
PRECEQU_PH(qbra, 16, 0);
1864

    
1865
#undef PRECEQU_PH
1866

    
1867
#if defined(TARGET_MIPS64)
1868
#define PRECEQU_QH(name, a, b, c, d) \
1869
target_ulong helper_precequ_qh_##name(target_ulong rt)       \
1870
{                                                            \
1871
    uint16_t tempD, tempC, tempB, tempA;                     \
1872
                                                             \
1873
    tempD = (rt >> a) & MIPSDSP_Q0;                          \
1874
    tempC = (rt >> b) & MIPSDSP_Q0;                          \
1875
    tempB = (rt >> c) & MIPSDSP_Q0;                          \
1876
    tempA = (rt >> d) & MIPSDSP_Q0;                          \
1877
                                                             \
1878
    tempD = tempD << 7;                                      \
1879
    tempC = tempC << 7;                                      \
1880
    tempB = tempB << 7;                                      \
1881
    tempA = tempA << 7;                                      \
1882
                                                             \
1883
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1884
}
1885

    
1886
PRECEQU_QH(obl, 56, 48, 40, 32);
1887
PRECEQU_QH(obr, 24, 16, 8, 0);
1888
PRECEQU_QH(obla, 56, 40, 24, 8);
1889
PRECEQU_QH(obra, 48, 32, 16, 0);
1890

    
1891
#undef PRECEQU_QH
1892

    
1893
#endif
1894

    
1895
#define PRECEU_PH(name, a, b) \
1896
target_ulong helper_preceu_ph_##name(target_ulong rt) \
1897
{                                                     \
1898
    uint16_t tempB, tempA;                            \
1899
                                                      \
1900
    tempB = (rt >> a) & MIPSDSP_Q0;                   \
1901
    tempA = (rt >> b) & MIPSDSP_Q0;                   \
1902
                                                      \
1903
    return MIPSDSP_RETURN32_16(tempB, tempA);         \
1904
}
1905

    
1906
PRECEU_PH(qbl, 24, 16);
1907
PRECEU_PH(qbr, 8, 0);
1908
PRECEU_PH(qbla, 24, 8);
1909
PRECEU_PH(qbra, 16, 0);
1910

    
1911
#undef PRECEU_PH
1912

    
1913
#if defined(TARGET_MIPS64)
1914
#define PRECEU_QH(name, a, b, c, d) \
1915
target_ulong helper_preceu_qh_##name(target_ulong rt)        \
1916
{                                                            \
1917
    uint16_t tempD, tempC, tempB, tempA;                     \
1918
                                                             \
1919
    tempD = (rt >> a) & MIPSDSP_Q0;                          \
1920
    tempC = (rt >> b) & MIPSDSP_Q0;                          \
1921
    tempB = (rt >> c) & MIPSDSP_Q0;                          \
1922
    tempA = (rt >> d) & MIPSDSP_Q0;                          \
1923
                                                             \
1924
    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
1925
}
1926

    
1927
PRECEU_QH(obl, 56, 48, 40, 32);
1928
PRECEU_QH(obr, 24, 16, 8, 0);
1929
PRECEU_QH(obla, 56, 40, 24, 8);
1930
PRECEU_QH(obra, 48, 32, 16, 0);
1931

    
1932
#undef PRECEU_QH
1933

    
1934
#endif
1935

    
1936
/** DSP GPR-Based Shift Sub-class insns **/
1937
#define SHIFT_QB(name, func) \
1938
target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \
1939
{                                                                    \
1940
    uint8_t rt3, rt2, rt1, rt0;                                      \
1941
                                                                     \
1942
    sa = sa & 0x07;                                                  \
1943
                                                                     \
1944
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
1945
                                                                     \
1946
    rt3 = mipsdsp_##func(rt3, sa);                                   \
1947
    rt2 = mipsdsp_##func(rt2, sa);                                   \
1948
    rt1 = mipsdsp_##func(rt1, sa);                                   \
1949
    rt0 = mipsdsp_##func(rt0, sa);                                   \
1950
                                                                     \
1951
    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
1952
}
1953

    
1954
#define SHIFT_QB_ENV(name, func) \
1955
target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\
1956
                                CPUMIPSState *env) \
1957
{                                                                    \
1958
    uint8_t rt3, rt2, rt1, rt0;                                      \
1959
                                                                     \
1960
    sa = sa & 0x07;                                                  \
1961
                                                                     \
1962
    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
1963
                                                                     \
1964
    rt3 = mipsdsp_##func(rt3, sa, env);                              \
1965
    rt2 = mipsdsp_##func(rt2, sa, env);                              \
1966
    rt1 = mipsdsp_##func(rt1, sa, env);                              \
1967
    rt0 = mipsdsp_##func(rt0, sa, env);                              \
1968
                                                                     \
1969
    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
1970
}
1971

    
1972
SHIFT_QB_ENV(shll, lshift8);
1973
SHIFT_QB(shrl, rshift_u8);
1974

    
1975
SHIFT_QB(shra, rashift8);
1976
SHIFT_QB(shra_r, rnd8_rashift);
1977

    
1978
#undef SHIFT_QB
1979
#undef SHIFT_QB_ENV
1980

    
1981
#if defined(TARGET_MIPS64)
1982
#define SHIFT_OB(name, func) \
1983
target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
1984
{                                                                        \
1985
    int i;                                                               \
1986
    uint8_t rt_t[8];                                                     \
1987
    uint64_t temp;                                                       \
1988
                                                                         \
1989
    sa = sa & 0x07;                                                      \
1990
    temp = 0;                                                            \
1991
                                                                         \
1992
    for (i = 0; i < 8; i++) {                                            \
1993
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
1994
        rt_t[i] = mipsdsp_##func(rt_t[i], sa);                           \
1995
        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
1996
    }                                                                    \
1997
                                                                         \
1998
    return temp;                                                         \
1999
}
2000

    
2001
#define SHIFT_OB_ENV(name, func) \
2002
target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
2003
                                CPUMIPSState *env)                       \
2004
{                                                                        \
2005
    int i;                                                               \
2006
    uint8_t rt_t[8];                                                     \
2007
    uint64_t temp;                                                       \
2008
                                                                         \
2009
    sa = sa & 0x07;                                                      \
2010
    temp = 0;                                                            \
2011
                                                                         \
2012
    for (i = 0; i < 8; i++) {                                            \
2013
        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
2014
        rt_t[i] = mipsdsp_##func(rt_t[i], sa, env);                      \
2015
        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
2016
    }                                                                    \
2017
                                                                         \
2018
    return temp;                                                         \
2019
}
2020

    
2021
SHIFT_OB_ENV(shll, lshift8);
2022
SHIFT_OB(shrl, rshift_u8);
2023

    
2024
SHIFT_OB(shra, rashift8);
2025
SHIFT_OB(shra_r, rnd8_rashift);
2026

    
2027
#undef SHIFT_OB
2028
#undef SHIFT_OB_ENV
2029

    
2030
#endif
2031

    
2032
#define SHIFT_PH(name, func) \
2033
target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \
2034
                                CPUMIPSState *env)                \
2035
{                                                                 \
2036
    uint16_t rth, rtl;                                            \
2037
                                                                  \
2038
    sa = sa & 0x0F;                                               \
2039
                                                                  \
2040
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
2041
                                                                  \
2042
    rth = mipsdsp_##func(rth, sa, env);                           \
2043
    rtl = mipsdsp_##func(rtl, sa, env);                           \
2044
                                                                  \
2045
    return MIPSDSP_RETURN32_16(rth, rtl);                         \
2046
}
2047

    
2048
SHIFT_PH(shll, lshift16);
2049
SHIFT_PH(shll_s, sat16_lshift);
2050

    
2051
#undef SHIFT_PH
2052

    
2053
#if defined(TARGET_MIPS64)
2054
#define SHIFT_QH(name, func) \
2055
target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \
2056
{                                                                 \
2057
    uint16_t rt3, rt2, rt1, rt0;                                  \
2058
                                                                  \
2059
    sa = sa & 0x0F;                                               \
2060
                                                                  \
2061
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
2062
                                                                  \
2063
    rt3 = mipsdsp_##func(rt3, sa);                                \
2064
    rt2 = mipsdsp_##func(rt2, sa);                                \
2065
    rt1 = mipsdsp_##func(rt1, sa);                                \
2066
    rt0 = mipsdsp_##func(rt0, sa);                                \
2067
                                                                  \
2068
    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
2069
}
2070

    
2071
#define SHIFT_QH_ENV(name, func) \
2072
target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \
2073
                                CPUMIPSState *env)                \
2074
{                                                                 \
2075
    uint16_t rt3, rt2, rt1, rt0;                                  \
2076
                                                                  \
2077
    sa = sa & 0x0F;                                               \
2078
                                                                  \
2079
    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
2080
                                                                  \
2081
    rt3 = mipsdsp_##func(rt3, sa, env);                           \
2082
    rt2 = mipsdsp_##func(rt2, sa, env);                           \
2083
    rt1 = mipsdsp_##func(rt1, sa, env);                           \
2084
    rt0 = mipsdsp_##func(rt0, sa, env);                           \
2085
                                                                  \
2086
    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
2087
}
2088

    
2089
SHIFT_QH_ENV(shll, lshift16);
2090
SHIFT_QH_ENV(shll_s, sat16_lshift);
2091

    
2092
SHIFT_QH(shrl, rshift_u16);
2093
SHIFT_QH(shra, rashift16);
2094
SHIFT_QH(shra_r, rnd16_rashift);
2095

    
2096
#undef SHIFT_QH
2097
#undef SHIFT_QH_ENV
2098

    
2099
#endif
2100

    
2101
#define SHIFT_W(name, func) \
2102
target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
2103
{                                                                       \
2104
    uint32_t temp;                                                      \
2105
                                                                        \
2106
    sa = sa & 0x1F;                                                     \
2107
    temp = mipsdsp_##func(rt, sa);                                      \
2108
                                                                        \
2109
    return (target_long)(int32_t)temp;                                  \
2110
}
2111

    
2112
#define SHIFT_W_ENV(name, func) \
2113
target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \
2114
                               CPUMIPSState *env) \
2115
{                                                                       \
2116
    uint32_t temp;                                                      \
2117
                                                                        \
2118
    sa = sa & 0x1F;                                                     \
2119
    temp = mipsdsp_##func(rt, sa, env);                                 \
2120
                                                                        \
2121
    return (target_long)(int32_t)temp;                                  \
2122
}
2123

    
2124
SHIFT_W_ENV(shll_s, sat32_lshift);
2125
SHIFT_W(shra_r, rnd32_rashift);
2126

    
2127
#undef SHIFT_W
2128
#undef SHIFT_W_ENV
2129

    
2130
#if defined(TARGET_MIPS64)
2131
#define SHIFT_PW(name, func) \
2132
target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \
2133
{                                                                 \
2134
    uint32_t rt1, rt0;                                            \
2135
                                                                  \
2136
    sa = sa & 0x1F;                                               \
2137
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
2138
                                                                  \
2139
    rt1 = mipsdsp_##func(rt1, sa);                                \
2140
    rt0 = mipsdsp_##func(rt0, sa);                                \
2141
                                                                  \
2142
    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
2143
}
2144

    
2145
#define SHIFT_PW_ENV(name, func) \
2146
target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \
2147
                                CPUMIPSState *env)                \
2148
{                                                                 \
2149
    uint32_t rt1, rt0;                                            \
2150
                                                                  \
2151
    sa = sa & 0x1F;                                               \
2152
    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
2153
                                                                  \
2154
    rt1 = mipsdsp_##func(rt1, sa, env);                           \
2155
    rt0 = mipsdsp_##func(rt0, sa, env);                           \
2156
                                                                  \
2157
    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
2158
}
2159

    
2160
SHIFT_PW_ENV(shll, lshift32);
2161
SHIFT_PW_ENV(shll_s, sat32_lshift);
2162

    
2163
SHIFT_PW(shra, rashift32);
2164
SHIFT_PW(shra_r, rnd32_rashift);
2165

    
2166
#undef SHIFT_PW
2167
#undef SHIFT_PW_ENV
2168

    
2169
#endif
2170

    
2171
#define SHIFT_PH(name, func) \
2172
target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
2173
{                                                                    \
2174
    uint16_t rth, rtl;                                               \
2175
                                                                     \
2176
    sa = sa & 0x0F;                                                  \
2177
                                                                     \
2178
    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                \
2179
                                                                     \
2180
    rth = mipsdsp_##func(rth, sa);                                   \
2181
    rtl = mipsdsp_##func(rtl, sa);                                   \
2182
                                                                     \
2183
    return MIPSDSP_RETURN32_16(rth, rtl);                            \
2184
}
2185

    
2186
SHIFT_PH(shrl, rshift_u16);
2187
SHIFT_PH(shra, rashift16);
2188
SHIFT_PH(shra_r, rnd16_rashift);
2189

    
2190
#undef SHIFT_PH
2191

    
2192
#undef MIPSDSP_LHI
2193
#undef MIPSDSP_LLO
2194
#undef MIPSDSP_HI
2195
#undef MIPSDSP_LO
2196
#undef MIPSDSP_Q3
2197
#undef MIPSDSP_Q2
2198
#undef MIPSDSP_Q1
2199
#undef MIPSDSP_Q0
2200

    
2201
#undef MIPSDSP_SPLIT32_8
2202
#undef MIPSDSP_SPLIT32_16
2203

    
2204
#undef MIPSDSP_RETURN32
2205
#undef MIPSDSP_RETURN32_8
2206
#undef MIPSDSP_RETURN32_16
2207

    
2208
#ifdef TARGET_MIPS64
2209
#undef MIPSDSP_SPLIT64_16
2210
#undef MIPSDSP_SPLIT64_32
2211
#undef MIPSDSP_RETURN64_16
2212
#undef MIPSDSP_RETURN64_32
2213
#endif