These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / target-alpha / int_helper.c
1 /*
2  *  Helpers for integer and multimedia instructions.
3  *
4  *  Copyright (c) 2007 Jocelyn Mayer
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 "qemu/osdep.h"
21 #include "cpu.h"
22 #include "exec/helper-proto.h"
23 #include "qemu/host-utils.h"
24
25
26 uint64_t helper_ctpop(uint64_t arg)
27 {
28     return ctpop64(arg);
29 }
30
31 uint64_t helper_ctlz(uint64_t arg)
32 {
33     return clz64(arg);
34 }
35
36 uint64_t helper_cttz(uint64_t arg)
37 {
38     return ctz64(arg);
39 }
40
41 uint64_t helper_zapnot(uint64_t val, uint64_t mskb)
42 {
43     uint64_t mask;
44
45     mask  = -(mskb & 0x01) & 0x00000000000000ffull;
46     mask |= -(mskb & 0x02) & 0x000000000000ff00ull;
47     mask |= -(mskb & 0x04) & 0x0000000000ff0000ull;
48     mask |= -(mskb & 0x08) & 0x00000000ff000000ull;
49     mask |= -(mskb & 0x10) & 0x000000ff00000000ull;
50     mask |= -(mskb & 0x20) & 0x0000ff0000000000ull;
51     mask |= -(mskb & 0x40) & 0x00ff000000000000ull;
52     mask |= -(mskb & 0x80) & 0xff00000000000000ull;
53
54     return val & mask;
55 }
56
57 uint64_t helper_zap(uint64_t val, uint64_t mask)
58 {
59     return helper_zapnot(val, ~mask);
60 }
61
62 uint64_t helper_cmpbe0(uint64_t a)
63 {
64     uint64_t m = 0x7f7f7f7f7f7f7f7fULL;
65     uint64_t c = ~(((a & m) + m) | a | m);
66     /* a.......b.......c.......d.......e.......f.......g.......h....... */
67     c |= c << 7;
68     /* ab......bc......cd......de......ef......fg......gh......h....... */
69     c |= c << 14;
70     /* abcd....bcde....cdef....defg....efgh....fgh.....gh......h....... */
71     c |= c << 28;
72     /* abcdefghbcdefgh.cdefgh..defgh...efgh....fgh.....gh......h....... */
73     return c >> 56;
74 }
75
76 uint64_t helper_cmpbge(uint64_t a, uint64_t b)
77 {
78     uint64_t mask = 0x00ff00ff00ff00ffULL;
79     uint64_t test = 0x0100010001000100ULL;
80     uint64_t al, ah, bl, bh, cl, ch;
81
82     /* Separate the bytes to avoid false positives.  */
83     al = a & mask;
84     bl = b & mask;
85     ah = (a >> 8) & mask;
86     bh = (b >> 8) & mask;
87
88     /* "Compare".  If a byte in B is greater than a byte in A,
89        it will clear the test bit.  */
90     cl = ((al | test) - bl) & test;
91     ch = ((ah | test) - bh) & test;
92
93     /* Fold all of the test bits into a contiguous set.  */
94     /* ch=.......a...............c...............e...............g........ */
95     /* cl=.......b...............d...............f...............h........ */
96     cl += ch << 1;
97     /* cl=......ab..............cd..............ef..............gh........ */
98     cl |= cl << 14;
99     /* cl=......abcd............cdef............efgh............gh........ */
100     cl |= cl << 28;
101     /* cl=......abcdefgh........cdefgh..........efgh............gh........ */
102     return cl >> 50;
103 }
104
105 uint64_t helper_minub8(uint64_t op1, uint64_t op2)
106 {
107     uint64_t res = 0;
108     uint8_t opa, opb, opr;
109     int i;
110
111     for (i = 0; i < 8; ++i) {
112         opa = op1 >> (i * 8);
113         opb = op2 >> (i * 8);
114         opr = opa < opb ? opa : opb;
115         res |= (uint64_t)opr << (i * 8);
116     }
117     return res;
118 }
119
120 uint64_t helper_minsb8(uint64_t op1, uint64_t op2)
121 {
122     uint64_t res = 0;
123     int8_t opa, opb;
124     uint8_t opr;
125     int i;
126
127     for (i = 0; i < 8; ++i) {
128         opa = op1 >> (i * 8);
129         opb = op2 >> (i * 8);
130         opr = opa < opb ? opa : opb;
131         res |= (uint64_t)opr << (i * 8);
132     }
133     return res;
134 }
135
136 uint64_t helper_minuw4(uint64_t op1, uint64_t op2)
137 {
138     uint64_t res = 0;
139     uint16_t opa, opb, opr;
140     int i;
141
142     for (i = 0; i < 4; ++i) {
143         opa = op1 >> (i * 16);
144         opb = op2 >> (i * 16);
145         opr = opa < opb ? opa : opb;
146         res |= (uint64_t)opr << (i * 16);
147     }
148     return res;
149 }
150
151 uint64_t helper_minsw4(uint64_t op1, uint64_t op2)
152 {
153     uint64_t res = 0;
154     int16_t opa, opb;
155     uint16_t opr;
156     int i;
157
158     for (i = 0; i < 4; ++i) {
159         opa = op1 >> (i * 16);
160         opb = op2 >> (i * 16);
161         opr = opa < opb ? opa : opb;
162         res |= (uint64_t)opr << (i * 16);
163     }
164     return res;
165 }
166
167 uint64_t helper_maxub8(uint64_t op1, uint64_t op2)
168 {
169     uint64_t res = 0;
170     uint8_t opa, opb, opr;
171     int i;
172
173     for (i = 0; i < 8; ++i) {
174         opa = op1 >> (i * 8);
175         opb = op2 >> (i * 8);
176         opr = opa > opb ? opa : opb;
177         res |= (uint64_t)opr << (i * 8);
178     }
179     return res;
180 }
181
182 uint64_t helper_maxsb8(uint64_t op1, uint64_t op2)
183 {
184     uint64_t res = 0;
185     int8_t opa, opb;
186     uint8_t opr;
187     int i;
188
189     for (i = 0; i < 8; ++i) {
190         opa = op1 >> (i * 8);
191         opb = op2 >> (i * 8);
192         opr = opa > opb ? opa : opb;
193         res |= (uint64_t)opr << (i * 8);
194     }
195     return res;
196 }
197
198 uint64_t helper_maxuw4(uint64_t op1, uint64_t op2)
199 {
200     uint64_t res = 0;
201     uint16_t opa, opb, opr;
202     int i;
203
204     for (i = 0; i < 4; ++i) {
205         opa = op1 >> (i * 16);
206         opb = op2 >> (i * 16);
207         opr = opa > opb ? opa : opb;
208         res |= (uint64_t)opr << (i * 16);
209     }
210     return res;
211 }
212
213 uint64_t helper_maxsw4(uint64_t op1, uint64_t op2)
214 {
215     uint64_t res = 0;
216     int16_t opa, opb;
217     uint16_t opr;
218     int i;
219
220     for (i = 0; i < 4; ++i) {
221         opa = op1 >> (i * 16);
222         opb = op2 >> (i * 16);
223         opr = opa > opb ? opa : opb;
224         res |= (uint64_t)opr << (i * 16);
225     }
226     return res;
227 }
228
229 uint64_t helper_perr(uint64_t op1, uint64_t op2)
230 {
231     uint64_t res = 0;
232     uint8_t opa, opb, opr;
233     int i;
234
235     for (i = 0; i < 8; ++i) {
236         opa = op1 >> (i * 8);
237         opb = op2 >> (i * 8);
238         if (opa >= opb) {
239             opr = opa - opb;
240         } else {
241             opr = opb - opa;
242         }
243         res += opr;
244     }
245     return res;
246 }
247
248 uint64_t helper_pklb(uint64_t op1)
249 {
250     return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
251 }
252
253 uint64_t helper_pkwb(uint64_t op1)
254 {
255     return ((op1 & 0xff)
256             | ((op1 >> 8) & 0xff00)
257             | ((op1 >> 16) & 0xff0000)
258             | ((op1 >> 24) & 0xff000000));
259 }
260
261 uint64_t helper_unpkbl(uint64_t op1)
262 {
263     return (op1 & 0xff) | ((op1 & 0xff00) << 24);
264 }
265
266 uint64_t helper_unpkbw(uint64_t op1)
267 {
268     return ((op1 & 0xff)
269             | ((op1 & 0xff00) << 8)
270             | ((op1 & 0xff0000) << 16)
271             | ((op1 & 0xff000000) << 24));
272 }
273
274 void helper_check_overflow(CPUAlphaState *env, uint64_t op1, uint64_t op2)
275 {
276     if (unlikely(op1 != op2)) {
277         arith_excp(env, GETPC(), EXC_M_IOV, 0);
278     }
279 }