Add qemu 2.4.0
[kvmfornfv.git] / qemu / target-mips / lmi_helper.c
1 /*
2  *  Loongson Multimedia Instruction emulation helpers for QEMU.
3  *
4  *  Copyright (c) 2011  Richard Henderson <rth@twiddle.net>
5  *
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 "exec/helper-proto.h"
22
23 /* If the byte ordering doesn't matter, i.e. all columns are treated
24    identically, then this union can be used directly.  If byte ordering
25    does matter, we generally ignore dumping to memory.  */
26 typedef union {
27     uint8_t  ub[8];
28     int8_t   sb[8];
29     uint16_t uh[4];
30     int16_t  sh[4];
31     uint32_t uw[2];
32     int32_t  sw[2];
33     uint64_t d;
34 } LMIValue;
35
36 /* Some byte ordering issues can be mitigated by XORing in the following.  */
37 #ifdef HOST_WORDS_BIGENDIAN
38 # define BYTE_ORDER_XOR(N) N
39 #else
40 # define BYTE_ORDER_XOR(N) 0
41 #endif
42
43 #define SATSB(x)  (x < -0x80 ? -0x80 : x > 0x7f ? 0x7f : x)
44 #define SATUB(x)  (x > 0xff ? 0xff : x)
45
46 #define SATSH(x)  (x < -0x8000 ? -0x8000 : x > 0x7fff ? 0x7fff : x)
47 #define SATUH(x)  (x > 0xffff ? 0xffff : x)
48
49 #define SATSW(x) \
50     (x < -0x80000000ll ? -0x80000000ll : x > 0x7fffffff ? 0x7fffffff : x)
51 #define SATUW(x)  (x > 0xffffffffull ? 0xffffffffull : x)
52
53 uint64_t helper_paddsb(uint64_t fs, uint64_t ft)
54 {
55     LMIValue vs, vt;
56     unsigned int i;
57
58     vs.d = fs;
59     vt.d = ft;
60     for (i = 0; i < 8; ++i) {
61         int r = vs.sb[i] + vt.sb[i];
62         vs.sb[i] = SATSB(r);
63     }
64     return vs.d;
65 }
66
67 uint64_t helper_paddusb(uint64_t fs, uint64_t ft)
68 {
69     LMIValue vs, vt;
70     unsigned int i;
71
72     vs.d = fs;
73     vt.d = ft;
74     for (i = 0; i < 8; ++i) {
75         int r = vs.ub[i] + vt.ub[i];
76         vs.ub[i] = SATUB(r);
77     }
78     return vs.d;
79 }
80
81 uint64_t helper_paddsh(uint64_t fs, uint64_t ft)
82 {
83     LMIValue vs, vt;
84     unsigned int i;
85
86     vs.d = fs;
87     vt.d = ft;
88     for (i = 0; i < 4; ++i) {
89         int r = vs.sh[i] + vt.sh[i];
90         vs.sh[i] = SATSH(r);
91     }
92     return vs.d;
93 }
94
95 uint64_t helper_paddush(uint64_t fs, uint64_t ft)
96 {
97     LMIValue vs, vt;
98     unsigned int i;
99
100     vs.d = fs;
101     vt.d = ft;
102     for (i = 0; i < 4; ++i) {
103         int r = vs.uh[i] + vt.uh[i];
104         vs.uh[i] = SATUH(r);
105     }
106     return vs.d;
107 }
108
109 uint64_t helper_paddb(uint64_t fs, uint64_t ft)
110 {
111     LMIValue vs, vt;
112     unsigned int i;
113
114     vs.d = fs;
115     vt.d = ft;
116     for (i = 0; i < 8; ++i) {
117         vs.ub[i] += vt.ub[i];
118     }
119     return vs.d;
120 }
121
122 uint64_t helper_paddh(uint64_t fs, uint64_t ft)
123 {
124     LMIValue vs, vt;
125     unsigned int i;
126
127     vs.d = fs;
128     vt.d = ft;
129     for (i = 0; i < 4; ++i) {
130         vs.uh[i] += vt.uh[i];
131     }
132     return vs.d;
133 }
134
135 uint64_t helper_paddw(uint64_t fs, uint64_t ft)
136 {
137     LMIValue vs, vt;
138     unsigned int i;
139
140     vs.d = fs;
141     vt.d = ft;
142     for (i = 0; i < 2; ++i) {
143         vs.uw[i] += vt.uw[i];
144     }
145     return vs.d;
146 }
147
148 uint64_t helper_psubsb(uint64_t fs, uint64_t ft)
149 {
150     LMIValue vs, vt;
151     unsigned int i;
152
153     vs.d = fs;
154     vt.d = ft;
155     for (i = 0; i < 8; ++i) {
156         int r = vs.sb[i] - vt.sb[i];
157         vs.sb[i] = SATSB(r);
158     }
159     return vs.d;
160 }
161
162 uint64_t helper_psubusb(uint64_t fs, uint64_t ft)
163 {
164     LMIValue vs, vt;
165     unsigned int i;
166
167     vs.d = fs;
168     vt.d = ft;
169     for (i = 0; i < 8; ++i) {
170         int r = vs.ub[i] - vt.ub[i];
171         vs.ub[i] = SATUB(r);
172     }
173     return vs.d;
174 }
175
176 uint64_t helper_psubsh(uint64_t fs, uint64_t ft)
177 {
178     LMIValue vs, vt;
179     unsigned int i;
180
181     vs.d = fs;
182     vt.d = ft;
183     for (i = 0; i < 4; ++i) {
184         int r = vs.sh[i] - vt.sh[i];
185         vs.sh[i] = SATSH(r);
186     }
187     return vs.d;
188 }
189
190 uint64_t helper_psubush(uint64_t fs, uint64_t ft)
191 {
192     LMIValue vs, vt;
193     unsigned int i;
194
195     vs.d = fs;
196     vt.d = ft;
197     for (i = 0; i < 4; ++i) {
198         int r = vs.uh[i] - vt.uh[i];
199         vs.uh[i] = SATUH(r);
200     }
201     return vs.d;
202 }
203
204 uint64_t helper_psubb(uint64_t fs, uint64_t ft)
205 {
206     LMIValue vs, vt;
207     unsigned int i;
208
209     vs.d = fs;
210     vt.d = ft;
211     for (i = 0; i < 8; ++i) {
212         vs.ub[i] -= vt.ub[i];
213     }
214     return vs.d;
215 }
216
217 uint64_t helper_psubh(uint64_t fs, uint64_t ft)
218 {
219     LMIValue vs, vt;
220     unsigned int i;
221
222     vs.d = fs;
223     vt.d = ft;
224     for (i = 0; i < 4; ++i) {
225         vs.uh[i] -= vt.uh[i];
226     }
227     return vs.d;
228 }
229
230 uint64_t helper_psubw(uint64_t fs, uint64_t ft)
231 {
232     LMIValue vs, vt;
233     unsigned int i;
234
235     vs.d = fs;
236     vt.d = ft;
237     for (i = 0; i < 2; ++i) {
238         vs.uw[i] -= vt.uw[i];
239     }
240     return vs.d;
241 }
242
243 uint64_t helper_pshufh(uint64_t fs, uint64_t ft)
244 {
245     unsigned host = BYTE_ORDER_XOR(3);
246     LMIValue vd, vs;
247     unsigned i;
248
249     vs.d = fs;
250     vd.d = 0;
251     for (i = 0; i < 4; i++, ft >>= 2) {
252         vd.uh[i ^ host] = vs.uh[(ft & 3) ^ host];
253     }
254     return vd.d;
255 }
256
257 uint64_t helper_packsswh(uint64_t fs, uint64_t ft)
258 {
259     uint64_t fd = 0;
260     int64_t tmp;
261
262     tmp = (int32_t)(fs >> 0);
263     tmp = SATSH(tmp);
264     fd |= (tmp & 0xffff) << 0;
265
266     tmp = (int32_t)(fs >> 32);
267     tmp = SATSH(tmp);
268     fd |= (tmp & 0xffff) << 16;
269
270     tmp = (int32_t)(ft >> 0);
271     tmp = SATSH(tmp);
272     fd |= (tmp & 0xffff) << 32;
273
274     tmp = (int32_t)(ft >> 32);
275     tmp = SATSH(tmp);
276     fd |= (tmp & 0xffff) << 48;
277
278     return fd;
279 }
280
281 uint64_t helper_packsshb(uint64_t fs, uint64_t ft)
282 {
283     uint64_t fd = 0;
284     unsigned int i;
285
286     for (i = 0; i < 4; ++i) {
287         int16_t tmp = fs >> (i * 16);
288         tmp = SATSB(tmp);
289         fd |= (uint64_t)(tmp & 0xff) << (i * 8);
290     }
291     for (i = 0; i < 4; ++i) {
292         int16_t tmp = ft >> (i * 16);
293         tmp = SATSB(tmp);
294         fd |= (uint64_t)(tmp & 0xff) << (i * 8 + 32);
295     }
296
297     return fd;
298 }
299
300 uint64_t helper_packushb(uint64_t fs, uint64_t ft)
301 {
302     uint64_t fd = 0;
303     unsigned int i;
304
305     for (i = 0; i < 4; ++i) {
306         int16_t tmp = fs >> (i * 16);
307         tmp = SATUB(tmp);
308         fd |= (uint64_t)(tmp & 0xff) << (i * 8);
309     }
310     for (i = 0; i < 4; ++i) {
311         int16_t tmp = ft >> (i * 16);
312         tmp = SATUB(tmp);
313         fd |= (uint64_t)(tmp & 0xff) << (i * 8 + 32);
314     }
315
316     return fd;
317 }
318
319 uint64_t helper_punpcklwd(uint64_t fs, uint64_t ft)
320 {
321     return (fs & 0xffffffff) | (ft << 32);
322 }
323
324 uint64_t helper_punpckhwd(uint64_t fs, uint64_t ft)
325 {
326     return (fs >> 32) | (ft & ~0xffffffffull);
327 }
328
329 uint64_t helper_punpcklhw(uint64_t fs, uint64_t ft)
330 {
331     unsigned host = BYTE_ORDER_XOR(3);
332     LMIValue vd, vs, vt;
333
334     vs.d = fs;
335     vt.d = ft;
336     vd.uh[0 ^ host] = vs.uh[0 ^ host];
337     vd.uh[1 ^ host] = vt.uh[0 ^ host];
338     vd.uh[2 ^ host] = vs.uh[1 ^ host];
339     vd.uh[3 ^ host] = vt.uh[1 ^ host];
340
341     return vd.d;
342 }
343
344 uint64_t helper_punpckhhw(uint64_t fs, uint64_t ft)
345 {
346     unsigned host = BYTE_ORDER_XOR(3);
347     LMIValue vd, vs, vt;
348
349     vs.d = fs;
350     vt.d = ft;
351     vd.uh[0 ^ host] = vs.uh[2 ^ host];
352     vd.uh[1 ^ host] = vt.uh[2 ^ host];
353     vd.uh[2 ^ host] = vs.uh[3 ^ host];
354     vd.uh[3 ^ host] = vt.uh[3 ^ host];
355
356     return vd.d;
357 }
358
359 uint64_t helper_punpcklbh(uint64_t fs, uint64_t ft)
360 {
361     unsigned host = BYTE_ORDER_XOR(7);
362     LMIValue vd, vs, vt;
363
364     vs.d = fs;
365     vt.d = ft;
366     vd.ub[0 ^ host] = vs.ub[0 ^ host];
367     vd.ub[1 ^ host] = vt.ub[0 ^ host];
368     vd.ub[2 ^ host] = vs.ub[1 ^ host];
369     vd.ub[3 ^ host] = vt.ub[1 ^ host];
370     vd.ub[4 ^ host] = vs.ub[2 ^ host];
371     vd.ub[5 ^ host] = vt.ub[2 ^ host];
372     vd.ub[6 ^ host] = vs.ub[3 ^ host];
373     vd.ub[7 ^ host] = vt.ub[3 ^ host];
374
375     return vd.d;
376 }
377
378 uint64_t helper_punpckhbh(uint64_t fs, uint64_t ft)
379 {
380     unsigned host = BYTE_ORDER_XOR(7);
381     LMIValue vd, vs, vt;
382
383     vs.d = fs;
384     vt.d = ft;
385     vd.ub[0 ^ host] = vs.ub[4 ^ host];
386     vd.ub[1 ^ host] = vt.ub[4 ^ host];
387     vd.ub[2 ^ host] = vs.ub[5 ^ host];
388     vd.ub[3 ^ host] = vt.ub[5 ^ host];
389     vd.ub[4 ^ host] = vs.ub[6 ^ host];
390     vd.ub[5 ^ host] = vt.ub[6 ^ host];
391     vd.ub[6 ^ host] = vs.ub[7 ^ host];
392     vd.ub[7 ^ host] = vt.ub[7 ^ host];
393
394     return vd.d;
395 }
396
397 uint64_t helper_pavgh(uint64_t fs, uint64_t ft)
398 {
399     LMIValue vs, vt;
400     unsigned i;
401
402     vs.d = fs;
403     vt.d = ft;
404     for (i = 0; i < 4; i++) {
405         vs.uh[i] = (vs.uh[i] + vt.uh[i] + 1) >> 1;
406     }
407     return vs.d;
408 }
409
410 uint64_t helper_pavgb(uint64_t fs, uint64_t ft)
411 {
412     LMIValue vs, vt;
413     unsigned i;
414
415     vs.d = fs;
416     vt.d = ft;
417     for (i = 0; i < 8; i++) {
418         vs.ub[i] = (vs.ub[i] + vt.ub[i] + 1) >> 1;
419     }
420     return vs.d;
421 }
422
423 uint64_t helper_pmaxsh(uint64_t fs, uint64_t ft)
424 {
425     LMIValue vs, vt;
426     unsigned i;
427
428     vs.d = fs;
429     vt.d = ft;
430     for (i = 0; i < 4; i++) {
431         vs.sh[i] = (vs.sh[i] >= vt.sh[i] ? vs.sh[i] : vt.sh[i]);
432     }
433     return vs.d;
434 }
435
436 uint64_t helper_pminsh(uint64_t fs, uint64_t ft)
437 {
438     LMIValue vs, vt;
439     unsigned i;
440
441     vs.d = fs;
442     vt.d = ft;
443     for (i = 0; i < 4; i++) {
444         vs.sh[i] = (vs.sh[i] <= vt.sh[i] ? vs.sh[i] : vt.sh[i]);
445     }
446     return vs.d;
447 }
448
449 uint64_t helper_pmaxub(uint64_t fs, uint64_t ft)
450 {
451     LMIValue vs, vt;
452     unsigned i;
453
454     vs.d = fs;
455     vt.d = ft;
456     for (i = 0; i < 4; i++) {
457         vs.ub[i] = (vs.ub[i] >= vt.ub[i] ? vs.ub[i] : vt.ub[i]);
458     }
459     return vs.d;
460 }
461
462 uint64_t helper_pminub(uint64_t fs, uint64_t ft)
463 {
464     LMIValue vs, vt;
465     unsigned i;
466
467     vs.d = fs;
468     vt.d = ft;
469     for (i = 0; i < 4; i++) {
470         vs.ub[i] = (vs.ub[i] <= vt.ub[i] ? vs.ub[i] : vt.ub[i]);
471     }
472     return vs.d;
473 }
474
475 uint64_t helper_pcmpeqw(uint64_t fs, uint64_t ft)
476 {
477     LMIValue vs, vt;
478     unsigned i;
479
480     vs.d = fs;
481     vt.d = ft;
482     for (i = 0; i < 2; i++) {
483         vs.uw[i] = -(vs.uw[i] == vt.uw[i]);
484     }
485     return vs.d;
486 }
487
488 uint64_t helper_pcmpgtw(uint64_t fs, uint64_t ft)
489 {
490     LMIValue vs, vt;
491     unsigned i;
492
493     vs.d = fs;
494     vt.d = ft;
495     for (i = 0; i < 2; i++) {
496         vs.uw[i] = -(vs.uw[i] > vt.uw[i]);
497     }
498     return vs.d;
499 }
500
501 uint64_t helper_pcmpeqh(uint64_t fs, uint64_t ft)
502 {
503     LMIValue vs, vt;
504     unsigned i;
505
506     vs.d = fs;
507     vt.d = ft;
508     for (i = 0; i < 4; i++) {
509         vs.uh[i] = -(vs.uh[i] == vt.uh[i]);
510     }
511     return vs.d;
512 }
513
514 uint64_t helper_pcmpgth(uint64_t fs, uint64_t ft)
515 {
516     LMIValue vs, vt;
517     unsigned i;
518
519     vs.d = fs;
520     vt.d = ft;
521     for (i = 0; i < 4; i++) {
522         vs.uh[i] = -(vs.uh[i] > vt.uh[i]);
523     }
524     return vs.d;
525 }
526
527 uint64_t helper_pcmpeqb(uint64_t fs, uint64_t ft)
528 {
529     LMIValue vs, vt;
530     unsigned i;
531
532     vs.d = fs;
533     vt.d = ft;
534     for (i = 0; i < 8; i++) {
535         vs.ub[i] = -(vs.ub[i] == vt.ub[i]);
536     }
537     return vs.d;
538 }
539
540 uint64_t helper_pcmpgtb(uint64_t fs, uint64_t ft)
541 {
542     LMIValue vs, vt;
543     unsigned i;
544
545     vs.d = fs;
546     vt.d = ft;
547     for (i = 0; i < 8; i++) {
548         vs.ub[i] = -(vs.ub[i] > vt.ub[i]);
549     }
550     return vs.d;
551 }
552
553 uint64_t helper_psllw(uint64_t fs, uint64_t ft)
554 {
555     LMIValue vs;
556     unsigned i;
557
558     ft &= 0x7f;
559     if (ft > 31) {
560         return 0;
561     }
562     vs.d = fs;
563     for (i = 0; i < 2; ++i) {
564         vs.uw[i] <<= ft;
565     }
566     return vs.d;
567 }
568
569 uint64_t helper_psrlw(uint64_t fs, uint64_t ft)
570 {
571     LMIValue vs;
572     unsigned i;
573
574     ft &= 0x7f;
575     if (ft > 31) {
576         return 0;
577     }
578     vs.d = fs;
579     for (i = 0; i < 2; ++i) {
580         vs.uw[i] >>= ft;
581     }
582     return vs.d;
583 }
584
585 uint64_t helper_psraw(uint64_t fs, uint64_t ft)
586 {
587     LMIValue vs;
588     unsigned i;
589
590     ft &= 0x7f;
591     if (ft > 31) {
592         ft = 31;
593     }
594     vs.d = fs;
595     for (i = 0; i < 2; ++i) {
596         vs.sw[i] >>= ft;
597     }
598     return vs.d;
599 }
600
601 uint64_t helper_psllh(uint64_t fs, uint64_t ft)
602 {
603     LMIValue vs;
604     unsigned i;
605
606     ft &= 0x7f;
607     if (ft > 15) {
608         return 0;
609     }
610     vs.d = fs;
611     for (i = 0; i < 4; ++i) {
612         vs.uh[i] <<= ft;
613     }
614     return vs.d;
615 }
616
617 uint64_t helper_psrlh(uint64_t fs, uint64_t ft)
618 {
619     LMIValue vs;
620     unsigned i;
621
622     ft &= 0x7f;
623     if (ft > 15) {
624         return 0;
625     }
626     vs.d = fs;
627     for (i = 0; i < 4; ++i) {
628         vs.uh[i] >>= ft;
629     }
630     return vs.d;
631 }
632
633 uint64_t helper_psrah(uint64_t fs, uint64_t ft)
634 {
635     LMIValue vs;
636     unsigned i;
637
638     ft &= 0x7f;
639     if (ft > 15) {
640         ft = 15;
641     }
642     vs.d = fs;
643     for (i = 0; i < 4; ++i) {
644         vs.sh[i] >>= ft;
645     }
646     return vs.d;
647 }
648
649 uint64_t helper_pmullh(uint64_t fs, uint64_t ft)
650 {
651     LMIValue vs, vt;
652     unsigned i;
653
654     vs.d = fs;
655     vt.d = ft;
656     for (i = 0; i < 4; ++i) {
657         vs.sh[i] *= vt.sh[i];
658     }
659     return vs.d;
660 }
661
662 uint64_t helper_pmulhh(uint64_t fs, uint64_t ft)
663 {
664     LMIValue vs, vt;
665     unsigned i;
666
667     vs.d = fs;
668     vt.d = ft;
669     for (i = 0; i < 4; ++i) {
670         int32_t r = vs.sh[i] * vt.sh[i];
671         vs.sh[i] = r >> 16;
672     }
673     return vs.d;
674 }
675
676 uint64_t helper_pmulhuh(uint64_t fs, uint64_t ft)
677 {
678     LMIValue vs, vt;
679     unsigned i;
680
681     vs.d = fs;
682     vt.d = ft;
683     for (i = 0; i < 4; ++i) {
684         uint32_t r = vs.uh[i] * vt.uh[i];
685         vs.uh[i] = r >> 16;
686     }
687     return vs.d;
688 }
689
690 uint64_t helper_pmaddhw(uint64_t fs, uint64_t ft)
691 {
692     unsigned host = BYTE_ORDER_XOR(3);
693     LMIValue vs, vt;
694     uint32_t p0, p1;
695
696     vs.d = fs;
697     vt.d = ft;
698     p0  = vs.sh[0 ^ host] * vt.sh[0 ^ host];
699     p0 += vs.sh[1 ^ host] * vt.sh[1 ^ host];
700     p1  = vs.sh[2 ^ host] * vt.sh[2 ^ host];
701     p1 += vs.sh[3 ^ host] * vt.sh[3 ^ host];
702
703     return ((uint64_t)p1 << 32) | p0;
704 }
705
706 uint64_t helper_pasubub(uint64_t fs, uint64_t ft)
707 {
708     LMIValue vs, vt;
709     unsigned i;
710
711     vs.d = fs;
712     vt.d = ft;
713     for (i = 0; i < 8; ++i) {
714         int r = vs.ub[i] - vt.ub[i];
715         vs.ub[i] = (r < 0 ? -r : r);
716     }
717     return vs.d;
718 }
719
720 uint64_t helper_biadd(uint64_t fs)
721 {
722     unsigned i, fd;
723
724     for (i = fd = 0; i < 8; ++i) {
725         fd += (fs >> (i * 8)) & 0xff;
726     }
727     return fd & 0xffff;
728 }
729
730 uint64_t helper_pmovmskb(uint64_t fs)
731 {
732     unsigned fd = 0;
733
734     fd |= ((fs >>  7) & 1) << 0;
735     fd |= ((fs >> 15) & 1) << 1;
736     fd |= ((fs >> 23) & 1) << 2;
737     fd |= ((fs >> 31) & 1) << 3;
738     fd |= ((fs >> 39) & 1) << 4;
739     fd |= ((fs >> 47) & 1) << 5;
740     fd |= ((fs >> 55) & 1) << 6;
741     fd |= ((fs >> 63) & 1) << 7;
742
743     return fd & 0xff;
744 }