1/*
2 *  x86 condition code helpers
3 *
4 *  Copyright (c) 2008 Fabrice Bellard
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.1 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#define DATA_BITS (1 << (3 + SHIFT))
21
22#if DATA_BITS == 8
23#define SUFFIX b
24#define DATA_TYPE uint8_t
25#define WIDER_TYPE uint32_t
26#elif DATA_BITS == 16
27#define SUFFIX w
28#define DATA_TYPE uint16_t
29#define WIDER_TYPE uint32_t
30#elif DATA_BITS == 32
31#define SUFFIX l
32#define DATA_TYPE uint32_t
33#if HOST_LONG_BITS >= 64
34#define WIDER_TYPE uint64_t
35#endif
36#elif DATA_BITS == 64
37#define SUFFIX q
38#define DATA_TYPE uint64_t
39#else
40#error unhandled operand size
41#endif
42
43#define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1))
44
45/* dynamic flags computation */
46
47static uint32_t glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
48{
49    uint32_t cf, pf, af, zf, sf, of;
50    DATA_TYPE src2 = dst - src1;
51
52    cf = dst < src1;
53    pf = compute_pf(dst);
54    af = (dst ^ src1 ^ src2) & CC_A;
55    zf = (dst == 0) * CC_Z;
56    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
57    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
58    return cf + pf + af + zf + sf + of;
59}
60
61static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
62{
63    return dst < src1;
64}
65
66static uint32_t glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
67                                         DATA_TYPE src3)
68{
69    uint32_t cf, pf, af, zf, sf, of;
70
71#ifdef WIDER_TYPE
72    WIDER_TYPE src13 = (WIDER_TYPE) src1 + (WIDER_TYPE) src3;
73    DATA_TYPE src2 = dst - src13;
74
75    cf = dst < src13;
76#else
77    DATA_TYPE src2 = dst - src1 - src3;
78
79    cf = (src3 ? dst <= src1 : dst < src1);
80#endif
81
82    pf = compute_pf(dst);
83    af = (dst ^ src1 ^ src2) & 0x10;
84    zf = (dst == 0) << 6;
85    sf = lshift(dst, 8 - DATA_BITS) & 0x80;
86    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
87    return cf + pf + af + zf + sf + of;
88}
89
90static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
91                                       DATA_TYPE src3)
92{
93#ifdef WIDER_TYPE
94    WIDER_TYPE src13 = (WIDER_TYPE) src1 + (WIDER_TYPE) src3;
95
96    return dst < src13;
97#else
98    return src3 ? dst <= src1 : dst < src1;
99#endif
100}
101
102static uint32_t glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
103{
104    uint32_t cf, pf, af, zf, sf, of;
105    DATA_TYPE src1 = dst + src2;
106
107    cf = src1 < src2;
108    pf = compute_pf(dst);
109    af = (dst ^ src1 ^ src2) & CC_A;
110    zf = (dst == 0) * CC_Z;
111    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
112    of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
113    return cf + pf + af + zf + sf + of;
114}
115
116static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
117{
118    DATA_TYPE src1 = dst + src2;
119
120    return src1 < src2;
121}
122
123static uint32_t glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
124                                         DATA_TYPE src3)
125{
126    uint32_t cf, pf, af, zf, sf, of;
127
128#ifdef WIDER_TYPE
129    WIDER_TYPE src23 = (WIDER_TYPE) src2 + (WIDER_TYPE) src3;
130    DATA_TYPE src1 = dst + src23;
131
132    cf = src1 < src23;
133#else
134    DATA_TYPE src1 = dst + src2 + src3;
135
136    cf = (src3 ? src1 <= src2 : src1 < src2);
137#endif
138
139    pf = compute_pf(dst);
140    af = (dst ^ src1 ^ src2) & 0x10;
141    zf = (dst == 0) << 6;
142    sf = lshift(dst, 8 - DATA_BITS) & 0x80;
143    of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
144    return cf + pf + af + zf + sf + of;
145}
146
147static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
148                                       DATA_TYPE src3)
149{
150#ifdef WIDER_TYPE
151    WIDER_TYPE src23 = (WIDER_TYPE) src2 + (WIDER_TYPE) src3;
152    DATA_TYPE src1 = dst + src23;
153
154    return src1 < src23;
155#else
156    DATA_TYPE src1 = dst + src2 + src3;
157
158    return (src3 ? src1 <= src2 : src1 < src2);
159#endif
160}
161
162static uint32_t glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
163{
164    uint32_t cf, pf, af, zf, sf, of;
165
166    cf = 0;
167    pf = compute_pf(dst);
168    af = 0;
169    zf = (dst == 0) * CC_Z;
170    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
171    of = 0;
172    return cf + pf + af + zf + sf + of;
173}
174
175static uint32_t glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
176{
177    uint32_t cf, pf, af, zf, sf, of;
178    DATA_TYPE src2;
179
180    cf = src1;
181    src1 = dst - 1;
182    src2 = 1;
183    pf = compute_pf(dst);
184    af = (dst ^ src1 ^ src2) & CC_A;
185    zf = (dst == 0) * CC_Z;
186    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
187    of = (dst == SIGN_MASK) * CC_O;
188    return cf + pf + af + zf + sf + of;
189}
190
191static uint32_t glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
192{
193    uint32_t cf, pf, af, zf, sf, of;
194    DATA_TYPE src2;
195
196    cf = src1;
197    src1 = dst + 1;
198    src2 = 1;
199    pf = compute_pf(dst);
200    af = (dst ^ src1 ^ src2) & CC_A;
201    zf = (dst == 0) * CC_Z;
202    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
203    of = (dst == SIGN_MASK - 1) * CC_O;
204    return cf + pf + af + zf + sf + of;
205}
206
207static uint32_t glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
208{
209    uint32_t cf, pf, af, zf, sf, of;
210
211    cf = (src1 >> (DATA_BITS - 1)) & CC_C;
212    pf = compute_pf(dst);
213    af = 0; /* undefined */
214    zf = (dst == 0) * CC_Z;
215    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
216    /* of is defined iff shift count == 1 */
217    of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
218    return cf + pf + af + zf + sf + of;
219}
220
221static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
222{
223    return (src1 >> (DATA_BITS - 1)) & CC_C;
224}
225
226static uint32_t glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
227{
228    uint32_t cf, pf, af, zf, sf, of;
229
230    cf = src1 & 1;
231    pf = compute_pf(dst);
232    af = 0; /* undefined */
233    zf = (dst == 0) * CC_Z;
234    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
235    /* of is defined iff shift count == 1 */
236    of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
237    return cf + pf + af + zf + sf + of;
238}
239
240/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
241   CF are modified and it is slower to do that.  Note as well that we
242   don't truncate SRC1 for computing carry to DATA_TYPE.  */
243static uint32_t glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1)
244{
245    uint32_t cf, pf, af, zf, sf, of;
246
247    cf = (src1 != 0);
248    pf = compute_pf(dst);
249    af = 0; /* undefined */
250    zf = (dst == 0) * CC_Z;
251    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
252    of = cf * CC_O;
253    return cf + pf + af + zf + sf + of;
254}
255
256static uint32_t glue(compute_all_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
257{
258    uint32_t cf, pf, af, zf, sf, of;
259
260    cf = (src1 == 0);
261    pf = 0; /* undefined */
262    af = 0; /* undefined */
263    zf = (dst == 0) * CC_Z;
264    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
265    of = 0;
266    return cf + pf + af + zf + sf + of;
267}
268
269static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
270{
271    return src1 == 0;
272}
273
274static int glue(compute_all_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
275{
276    uint32_t cf, pf, af, zf, sf, of;
277
278    cf = (src1 != 0);
279    pf = 0; /* undefined */
280    af = 0; /* undefined */
281    zf = (dst == 0) * CC_Z;
282    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
283    of = 0;
284    return cf + pf + af + zf + sf + of;
285}
286
287static int glue(compute_c_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
288{
289    return src1 != 0;
290}
291
292#undef DATA_BITS
293#undef SIGN_MASK
294#undef DATA_TYPE
295#undef DATA_MASK
296#undef SUFFIX
297#undef WIDER_TYPE
298